简介:通用字符串代码包括Latin1,UTF-8,UTF-16,GB18030。他们具有自己的特征,它们之间的转换更加复杂。这篇文章将介绍提高Java字符串编码的解码性能的技能。
作者|Wen Shaojin(高速导轨)
来源|阿里的开发人员公共帐户
常见的字符串代码是:
为了计算便利性,内存中的字符串通常使用均等的字符,并且在Java语言中使用utf-16中的char和.net中的字符。16.。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
UTF-16和UTF-8之间的转换更为复杂,而且性能较差。
以下是将UTF-16转换为UTF-8编码的实现。可以看出,该算法更为复杂,因此性能很差。无法使用向量API优化此操作。
相关代码地址[1]。
由于Java中的Char是UTF-16LE编码,因此,如果您需要将char []转换为utf-16le编码字节[],则可以使用sun.misc.unsafe#copymemory方法快速复制。例如:
JDK字符串的实现的不同版本是不同的,导致了不同的性能。CHAR是UTF-16编码,但是String可以在JDK 9之后的LATIN1编码内部编码。
3.1。JDK 6之前的字符串
在Java 6之前,由字符串生成的字符串对象与原始字符串对象共享一个char []值,这会导致gc恢复子字符串方法的字符串后的char []。,许多库将避免使用JDK 6及以下的子字符串方法。
3.2。JDK 7/8字符串实现
在JDK 7之后,字符串删除了偏移和计数字段,并且值。长度是原始计数。这避免了子字母引用大char []的问题,并且更易于优化,因此String在JDK7/8比Java 6大得多。
3.3。JDK 9/10/11实施
在JDK 9之后,值类型从char []转换为字节[],添加字段代码。如果字符都是ASCII字符,请使用值来使用拉丁编码;如果存在任何非ASCII字符,请使用UTF16。这种混合编码方法使英文场景的内存更少。缺点是Java 9的字符串API性能可能不如JDK 8,尤其是通过的构造函数字符串传递进入char []构造函数,将通过拉丁编码通过字节[]压缩。一些场景将减少10%。
为了实现字符串的非变量特征,在构造字符串时将有副本的副本。如果您想增加构造函数字符串的开销,则必须避免使用这种副本。
例如,实现JDK8字符串的构造函数
在JDK8中,有一个无需复制的构造函数,但是此方法不是公开的。您需要使用一种技术来实现MethodHandles.lookup&lambdametafactory来调用反射。有一个代码可以在文章背后介绍此技术。
有三种构建字符的方法:
这三种方法类似于1和2性能,3至1和2稍慢,但是它们比直接新字符串快得多。JDK8的数据使用JMH测试如下:
在JDK 9(所有ASCII字符的场景)之后,直接结构可以取得更好的结果。
4.1 MethodHandles.LOOKUP和LAMBDAMETAFACTORCORY绑定反射快速构造字符串方法。
相关代码地址[2]。
4.1.1 JDK8快速构造字符串
4.1.2 JDK 11快速构造字符串的方法
4.1.3 JDK 17快速构造字符串的方法
在JDK 17中,MethodHandles.lookup使用Reflection.RegisterFieldStofilter保护LookupClass和允许的模板。它不能用于在线修改允许模式的方法。
在JDK 17中,必须使用MethodHandlers来启动JVM启动参数。
4.2基于Javalangaccess的快速构造函数
由共享销售提供的Javalangaccess无法在不复制的情况下复制构造函数字符串,但这更麻烦。JDK 8/11/17的API不同。使用与不同JDK版本兼容的不同代码并不方便。不建议使用它。
4.3以实现基于不安全的快速构造字符串
注意:在JDK 9之后,实施方式不同,例如:
4.4快速构造字符串的技能应用:
以下方法格式日期是字符串,性能将非常好。
无论哪种版本的JDK,String.Charat都是大开销。JIT的优化效果不好。它无法消除参数索引范围检测的开销。最好直接在字符串中操作值数组。
在JDK 9之后的版本之后,Charat的开销更大
5.1如何获取字符串。值
获得字符串的方法。值如下:
在JDK 8 JMH上反映了不安全和场的比较数据如下:
5.1.1使用reflex获得字符串。
5.1.2使用不安全获取字符串。值
当您可以直接获取字符串。值时,您可以直接执行EncodeUTF8操作。
6.1 JDK8高绩效Encodeutf8的方法
带有encodeutf8方法的示例
这样,EncoDeUTF8操作将不会具有多余的阵列操作,并且性能将得到改善。
6.1.1性能测试比较
测试代码
检测结果
从结果来看,EncoDeUTF8方法是直接通过不安全 +调用的。编码所需的开销是NewsTringUtf8的58%。
6.2 JDK9/11/17的方法高性能Encodeutf8
带有encodeutf8方法的示例
这样,EncoDeUTF8操作将不会具有多余的阵列操作,并且性能将得到改善。
这些技术不用于新手。不当使用将很容易导致错误。如果您不完全理解它,请不要使用它!
参考链接:
[1] fastjson2/ioutils.java at 2.0.3·阿里巴巴/fastjson2·github
[2] fastjson2/jdkutils.java at 2.0.3·阿里巴巴/fastjson2·github
原始链接
本文是阿里巴巴云的原始内容,未经许可就无法重印。
原始:https://juejin.cn/post/7101178182195216397