在Android/Java中格式化MAC地址,而不创建不必要的垃圾

在Android/Java中格式化MAC地址,而不创建不必要的垃圾,java,android,garbage-collection,Java,Android,Garbage Collection,我正在开发一个Android应用程序,它需要每秒处理数千个数据包,同时提取和格式化每个帧的MAC地址。问题是垃圾收集器每秒运行十几次并使我的应用程序暂停,这反过来又使我错过了数据包。我尽可能避免创建新对象 我在DDMS中使用了分配跟踪器,并确定99%正在清理的垃圾来自以下方法。以下是我正在使用的代码: void parseMac() { hex_sb.setLength(0); for (hex_counter = 0; hex_counter < 6; hex_cou

我正在开发一个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();
}
void parseMac(){
十六进制设置长度(0);
用于(十六进制计数器=0;十六进制计数器<6;十六进制计数器++){
hex_sb.append(String.format(“%02X”,解析器_数据包_字节[解析器_跳过+十六进制计数器]);
如果(!(十六进制计数器==5)){
十六进制附加(“:”);
}
}
格式化的\u mac=hex\u sb.toString();
}
hex_sb是一个StringBuilder,可以重用。hex_计数器是MAC地址中的字节数(字节来自解析器_数据包_字节,一个字节[])。如果它不是MAC的最后一个字节,请附加“:”以正确格式化。formatted_mac是一个类范围的字符串,用于存储格式化的mac。根据分配跟踪器,唯一的问题是使用String.format的行


我向StackOverflow专家提出的问题是:如何重写上述方法以减少(最好是不创建)垃圾?

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

而不是使用非常昂贵的
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地址(已知长度)并且被称为整段,我可能会展开整个过程,包括添加冒号/句点(应该是
字符,而不是
字符串)。如果它确实对速度至关重要,请管理您自己的
char[]
并将其提供给
String\new(char[])
。这样可以避免重新插入分隔符。

为什么?你真的是每秒收到数千个不同同龄人的来信吗?或者,您是否每秒从同一对等方接收数千帧?在后一种情况下,每个帧中的MAC地址将是相同的。但是没有理由不能在没有循环的情况下,在单个
format()
调用中格式化整个MAC地址。那将把垃圾除以6。谢谢!我没有想过这样做。这个方法完全解决了这个问题,效果很好。我之前验证了我的结果,看起来这个方法没有正常工作。例如:当我使用这些字节作为MAC地址时:“0x58”“0x6D”“0x8F”“0xBA”“0xF5”“0x81”hex_sb.getString()给出了“58:6C:8E:A0:E5:81”。我对位转换不是很在行,我非常感谢你的洞察力……几乎不可能以这种方式失败。有可能是Java一直都在签名的失败,但这种失败模式毫无意义。如果你失败了,请发布一个完整的测试用例。