5

我正在开发一个 Android 应用程序,该应用程序需要每秒处理数千个数据包,同时提取和格式化每个帧的 MAC 地址。问题是垃圾收集器每秒运行十几次并停止我的应用程序,这反过来又让我错过了数据包。我尽可能(我认为)避免创建新对象。

我在 DDMS 中使用了分配跟踪器,并确定正在清理的 99% 的垃圾来自以下方法。这是我正在使用的代码:

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 是一个 StringBuilder,可以重用。hex_counter 是 MAC 地址中的字节数(字节来自 parser_packet_bytes,一个 byte[])。如果它不是 MAC 的最后一个字节,则附加一个“:”以进行正确格式化。formatted_mac 是一个类范围的字符串,用于存储格式化的 MAC。根据分配跟踪器,唯一的问题是使用 String.format 的行。

我对 StackOverflow 专家的问题是:如何重写上述方法以减少(最好没有)垃圾的产生?

4

2 回答 2

3

而不是使用String.format()非常昂贵的,只需手动附加半字节。不幸的是,ASCII/UTF-8 中的数字和字母不连续,所以我将如何处理它:

static final char HEX_DIGITS[] = "01234567890abcdef".toCharArray();
...
hex_sb.append(HEX_DIGITS[thisByte >> 4]).append(HEX_DIGITS[thisByte & 0xf]);

由于这是一个 MAC 地址(已知长度)并且被大量调用,我可能会展开整个事情,包括附加冒号/句点(应该是 a char,而不是 a String)。如果它真的对速度至关重要,请自行管理char[]并将其提供给String#new(char[]). 您可以避免以这种方式重新插入分隔符。

于 2013-08-25T04:58:45.987 回答
1

每个新的 MAC 都需要一个新的字符串,因为字符串是不可变的,所以你无能为力。至于 StringBuilder 操作,它不会创建任何垃圾,因为 StringBuilder 将在 setLength(0) 上重用相同的 char 数组并追加,它只会更改当前位置。唯一有帮助的是直接使用 StringBuilder 而不将其转换为 String 如果可能的话。

于 2013-08-25T04:50:17.770 回答