Java:字符串(byte[])的更快替代品

2022-09-04 02:25:55

我正在为二进制数据开发一个基于Java的下载器。此数据通过基于文本的协议(UU 编码)传输。对于网络任务,使用 netty 库。二进制数据被服务器拆分成数千个小数据包并发送到客户端(即Java应用程序)。

netty,每次收到新消息(数据)时,我都会收到一个对象。现在我需要处理这些数据,除了其他任务之外,我还需要检查来自服务器的包的标头(如HTTP状态行)。为此,我调用以接收数组。然后,我可以通过此数组转换为字符串,并轻松检查(例如比较)其内容(再次,例如与HTTP中的“200”状态消息进行比较)。ChannelBufferChannelBuffer.array()byte[]new String(byte[])

我正在编写的软件使用多个线程/连接,因此我并行接收来自netty的多个数据包。

这通常工作正常,但是,在分析应用程序时,我注意到,当与服务器的连接良好并且数据进入得非常快时,这种到对象的转换似乎是一个瓶颈。在这种情况下,CPU使用率接近100%,并且根据探查器,调用此构造函数花费了大量时间。StringString(byte[])

我寻找一种更好的方法来从到a,并注意到前者也有一种方法。但是,该方法甚至比构造函数慢。ChannelBufferStringtoString()String(byte[])

所以我的问题是:你们中是否有人知道更好的替代方案来实现我正在做的事情?


答案 1

也许您可以完全跳过字符串转换?您可以使用常量来保存比较值的字节数组,并检查数组到数组而不是字符串到字符串。

下面是一些快速代码来说明。目前,您正在执行类似操作:

String http200 = "200";
// byte[] -> String conversion happens every time
String input = new String(ChannelBuffer.array());
return input.equals(http200);

也许这更快:

// Ideally only convert String->byte[] once.  Store these
// arrays somewhere and look them up instead of recalculating.
final byte[] http200 = "200".getBytes("UTF-8"); // Select the correct charset!
// Input doesn't have to be converted!
byte[] input = ChannelBuffer.array();
return Arrays.equals(input, http200);

答案 2

您正在执行的一些检查可能只查看缓冲区的一部分。如果可以使用字符串构造函数的替代形式:

new String(byteArray, startCol, length)

这可能意味着转换为字符串的字节要少得多。

您在消息中查找“200”的示例就是一个示例。

2

您可能会发现可以使用字节数组的长度作为线索。如果某些消息很长,而您正在寻找一条短消息,请忽略较长的消息,不要转换为字符。或类似的东西。

3

除了@EricGrunzke所说的,在字节缓冲区中部分查看以过滤掉一些消息,并发现您不需要将它们从字节转换为字符。

4

如果字节是 ASCII 字符,则使用字符集“ASCII”而不是服务器的默认值,则转换为字符的速度可能会更快:

new String(bytes, "ASCII")

在这种情况下可能会更快。

实际上,您可能能够以某种有组织的方式选择转换字节字符的字符集,从而加快速度。


推荐