For a recent lab at the university we had to match the longest prefix for an IP (v4) address by using a Trie data structure. The code works fine, but it takes about 2 minutes to load a 14 million-line routing table. I examined what was causing the slowness, and it was the (String
) IP to (String
) binary format conversion.
For example, the IP address 127.0.0.1
should be converted to 01111111000000000000000000000001
. I my original method (slow
) uses String.format
, which I find much more readable and easy to follow. I then wrote a different method using a temporary char[]
, filled with '0'
to use as padding.
The speedup of the fast
method is about 6x. Below is a stripped down version for demonstration and measurement:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
final String ip = "127.0.0.1";
String binaryIp;
final long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i ++) {
binaryIp = fast(ip);
}
long fast = System.currentTimeMillis();
for (int i = 0; i < 10000000; i ++) {
binaryIp = slow(ip);
}
long slow = System.currentTimeMillis();
System.out.println("Fast time: " + (fast - start) + " ms");
System.out.println("Slow time: " + (slow - fast) + " ms");
}
public static String fast(String ip) {
StringBuilder bStringBuilder = new StringBuilder();
String ipParts[] = ip.split("\\.");
for (String ipPart : ipParts) {
String binString = Integer.toBinaryString(Integer.parseInt(ipPart));
int length = 8 - binString.length();
char[] padArray = new char[length];
Arrays.fill(padArray, '0');
bStringBuilder.append(padArray).append(binString);
}
System.out.println(bStringBuilder.toString());
return bStringBuilder.toString();
}
public static String slow(String ip) {
StringBuilder bStringBuilder = new StringBuilder();
String ipParts[] = ip.split("\\.");
for (String ipPart : ipParts) {
String binString = Integer.toBinaryString(Integer.parseInt(ipPart));
String binaryPart = String.format("%8s", binString).replace(' ', '0');
bStringBuilder.append(binaryPart);
}
return bStringBuilder.toString();
}
}
For which the output is:
Fast time: 3936 ms
Slow time: 23527 ms
I can't think of a more efficient way to pad a binary string appropriately... I don't think that there's any need to improve the slow
method as it's now obsolete compared to fast
. However, is there any way that I can improve fast
?
PS - magic number 8 would be a magic number that never changes, so I don't think I need a static final int ipv4SectionLength = 8
or anything like that!
Map<String, String>
for this. \$\endgroup\$