【发布时间】:2011-11-07 23:15:43
【问题描述】:
在任何人质疑使用string.intern() 的事实之前,让我说,出于内存和性能原因,我在我的特定应用程序中需要它。 [1]
所以,到目前为止,我一直使用String.intern(),并认为这是最有效的方法。但是,我注意到自古以来它就是软件的一个瓶颈。 [2]
然后,就在最近,我尝试用一个巨大的地图替换String.intern(),我在其中放置/获取字符串,以便每次都获得一个唯一的实例。我预计这会更慢......但事实恰恰相反!它的速度非常快!通过推送/轮询地图(实现完全相同)替换intern(),速度提高了一个数量级以上。
问题是:为什么intern() 这么慢?!?为什么它不简单地由地图(或者实际上,只是一个定制的集合)支持并且会非常快?我很困惑。
[1]:对于不相信的人:它属于自然语言处理,必须处理千兆字节的文本,因此需要避免同一字符串的多个实例以避免炸毁内存和引用字符串比较足够快.
[2]:没有它(普通字符串)是不可能的,有了它,这个特定的步骤仍然是最密集的计算步骤
编辑:
由于对这篇文章的惊人兴趣,这里有一些代码来测试它:
还有超过 100 万个字符串的实习结果:
-
HashMap:4 秒 -
String.intern():54 秒
为了避免一些预热/操作系统 IO 缓存和类似的东西,通过颠倒两个基准的顺序重复实验:
-
String.intern():69 秒 -
HashMap:3 秒
如您所见,差异非常明显,超过十倍。 (使用 OpenJDK 1.6.0_22 64bits ...但我认为使用 sun 的结果相似)
【问题讨论】:
-
好问题,你能给出一些关于
intern()慢多少的指标吗? -
你最终分配了多少个字符串实例到地图/实习?
-
您是将
intern与同步的Hashtable还是未同步的HashMap进行比较?intern是同步的,所以这可能是您所看到的大部分内容。 -
什么样的字符串操作? (例如子字符串提取与删除/编辑与连接)您可能想查看绳索。我也很好奇你是如何得到字符串的:当你做 readline() 或其他什么时,字符串是 equal() 不同的对象吗?!
-
你的实现线程安全吗?它是否使用弱引用?
标签: java string performance