java – String.intern()的性能损失

很多人谈论String.intern()的性能优势,但我实际上更关心性能损失。

我主要关注的是:

>搜索成本:intern()用于确定可变字符串是否存在于常量池中的时间。它如何成本与该池中的字符串数量成比例?
>同步:显然,常量池由整个JVM共享。当intern()从多个线程被调用时,该池如何表现?它执行多少锁定?性能如何与竞争衡量?

我关心所有这些事情,因为我目前正在一个财务应用程序,有一个使用太多的内存,由于重复的字符串的问题。一些字符串基本上看起来像枚举值,并且只有有限数量的潜在值(例如货币名称(“USD”,“EUR”))存在超过一百万份。 String.intern()在这种情况下似乎是一个没有脑子,但我担心调用intern()每次我存储货币在某处的同步开销。

最重要的是,一些其他类型的字符串可以有数百万不同的值,但仍然有每个的成千上万的副本(如ISIN代码)。对于这些,我担心interning一个百万字符串将基本上减慢intern()方法,以至于淹没我的应用程序。

我做了一点基准自己。对于搜索成本部分,我决定将String.intern()与ConcurrentHashMap.putIfAbsent(s,s)进行比较。基本上,这两个方法做同样的事情,除了String.intern()是一个本地方法,存储和读取从直接在JVM中管理的SymbolTable,ConcurrentHashMap.putIfAbsent()只是一个正常的实例方法。

你可以在github gist找到基准代码(因为缺乏一个更好的地方放置它)。您还可以在源文件顶部的注释中找到启动JVM时使用的选项(以验证基准不会偏斜)。

无论如何这里的结果:

搜索费用(单线程)

传说

> count:我们尝试汇集的不同字符串的数量
> initial intern:以毫秒为单位插入字符串池中的所有字符串的时间
> lookup same string:从池中再次查找每个字符串所用的时间(以毫秒为单位),使用与以前在池中输入的实例完全相同的实例
> lookup equal string:从池中再次查找每个字符串所需的时间(以毫秒为单位),但使用不同的实例

String.intern()

count       initial intern   lookup same string  lookup equal string
1'000'000            40206                34698                35000
  400'000             5198                 4481                 4477
  200'000              955                  828                  803
  100'000              234                  215                  220
   80'000              110                   94                   99
   40'000               52                   30                   32
   20'000               20                   10                   13
   10'000                7                    5                    7

ConcurrentHashMap.putIfAbsent()

count       initial intern   lookup same string  lookup equal string
1'000'000              411                  246                  309
  800'000              352                  194                  229
  400'000              162                   95                  114
  200'000               78                   50                   55
  100'000               41                   28                   28
   80'000               31                   23                   22
   40'000               20                   14                   16
   20'000               12                    6                    7
   10'000                9                    5                    3

搜索成本的结论:String.intern()是非常昂贵的调用。它非常糟糕,在O(n)的东西,其中n是池中的字符串数量。当池中的字符串数量增长时,从池中查找一个字符串的时间增长更多(每个查找10.7000个字符串,每个查询有0.7微秒,每个查询有1’000’000个字符串,40微秒)。

ConcurrentHashMap按预期缩放,池中的字符串数量对查找速度没有影响。

基于这个实验,我强烈建议避免使用String.intern()如果你要实习超过几个字符串。

http://stackoverflow.com/questions/10624232/performance-penalty-of-string-intern

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:java – String.intern()的性能损失