I am working on an Android app which needs to process thousands of packets per second while extracting and formatting the MAC address of each frame. The problem is that the garbage collector is running a dozen times per second and stalling my app, which in turn makes me miss packets. I have avoided creating new objects as much as (I think) possible.
I have used the allocation tracker in DDMS and determined that 99% of the garbage being cleaned up is coming from the following method. Here is the code I am using:
void parseMac() {
hex_sb.setLength(0);
for (hex_counter = 0; hex_counter < 6; hex_counter++) {
hex_sb.append(String.format("%02X", parser_packet_bytes[parser_skip + hex_counter]));
if (!(hex_counter == 5)) {
hex_sb.append(":");
}
}
formatted_mac = hex_sb.toString();
}
hex_sb is a StringBuilder, which gets reused. hex_counter is the number of bytes in a MAC address (bytes come from parser_packet_bytes, a byte[]). If it's not the last byte of the MAC, append a ":" for proper formatting. formatted_mac is a class-wide String that stores the formatted MAC. According to the allocation tracker, the only problem is the line using String.format.
My question to the StackOverflow experts is: how can I rewrite the above method so that less (preferrably no) garbage is created?
Instead of using String.format()
, which is quite expensive, just manually append the nibbles. Unfortunately, the digits and letters aren't contiguous in ASCII/UTF-8, so here's how I'd handle it:
static final char HEX_DIGITS[] = "01234567890abcdef".toCharArray();
...
hex_sb.append(HEX_DIGITS[thisByte >> 4]).append(HEX_DIGITS[thisByte & 0xf]);
Since this is a MAC address (known length) and gets called a whole lot, I would probably unroll the whole thing, including appending the colon/period (which should be a char
, not a String
). If it's really speed-critical, manage your own char[]
and feed it to String#new(char[])
. You could avoid re-inserting the delimiters that way.
Each new MAC will need a new String, you cant help it since String is immutable. As for StringBuilder manipulations it does not create any garbage as StringBuilder will reuse the same char array on setLength(0) and append, it will only change the current position. The only thing which would help is to work with StringBuilder directly without converting it to String if only it is possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With