关于如何提高Java String到byte []转换性能的任何建议?

Tim*_*sch 5 java performance java-native-interface

我继承了一段代码,它们大量使用String - > byte []转换,反之亦然,对于一些自行开发的序列化代码.本质上,Java对象知道如何将它们的组成部分转换为字符串,然后转换为字节[].然后,所述字节数组通过JNI传递给C++代码,该代码将byte []重构为C++ std :: strings,并使用它们来引导镜像Java对象的C++对象.还有一点,但这是对这段代码如何工作的高级视图; 通信在这两个方向上都是这样的,这样C++ - > Java转换就是我上面提到的Java - > C++转换的镜像.

这段代码的一部分 - 将字符串实际转换为字节[] - 在分析器中意外地显示为刻录了大量CPU.当然,有很多数据正在转移,但这是一个意想不到的瓶颈.

代码的基本概要如下:

public void convertToByteArray(String convert_me, ByteArrayOutputStream stream)
{
  stream.write(convert_me.getBytes());
}
Run Code Online (Sandbox Code Playgroud)

功能还有一点但不多.对于每个String/Stringified对象调用上述函数一次,并且在将所有成分写入ByteArrayOutputStream之后,ByteArrayOutputStream将转换为byte [].通过提取convert_me.getBytes()调用将上述内容分解为更适合剖析器的版本,可以看出此函数中90%以上的时间都花在了getBytes()调用上.

有没有办法改善getBytes()调用的性能,还是有另一种可能更快的方法来实现相同的转换?

正在转换的对象数量非常大.在仅使用生产数据的一小部分的分析运行中,我看到了1000万以上的调用上述转换函数.

由于我们非常接近将项目投入生产,因此目前还有一些不可行的解决方法:

  • 重写序列化接口只是在JNI层上传递String对象.这是改善情况的明显(对我而言)方式,但它需要对序列化层进行重大再造.鉴于本周早些时候我们将进入UAT,现在进行这种复杂的改变已经为时已晚.这是我下一个版本的顶级待办事项,所以它将完成; 然而,我确实需要一个解决方法,直到那时,但到目前为止代码工作,已经使用了多年,并且已经解决了大部分问题.好吧,除了表现.
  • 更改JVM(当前为1.5)也不是一种选择.不幸的是,这是安装在客户端计算机上的默认JVM,并且很可能无法更新到1.6(在这种情况下可能会或可能不会更快).任何在大型组织工作的人都可能理解为什么......
  • 除此之外,我们已经遇到内存限制,因此尝试至少缓存较大的字符串及其字节数组表示,同时作为一种可能优雅的解决方案,可能会导致更多问题而不是解决

Dav*_*veR 4

我猜测部分问题可能是 Java 字符串采用 UTF-16 格式 - 即每个字符两个字节;因此,getBytes()需要做大量工作将每个 UTF-16 元素转换为一个或两个字节,具体取决于您当前的字符集。

您是否尝试过使用CharsetEncoder - 这应该可以让您更好地控制字符串编码,并允许您跳过默认实现中的一些开销getBytes

或者,您是否尝试将字符集显式指定为getBytes,并使用US-ASCII作为字符集?