Java 8字符串重复数据消除与String.intern()的比较
我正在阅读Java 8 update 20中关于字符串重复数据消除()的功能,但我不确定这是否会使Java 8字符串重复数据消除与String.intern()的比较,java,string,jvm-hotspot,deduplication,Java,String,Jvm Hotspot,Deduplication,我正在阅读Java 8 update 20中关于字符串重复数据消除()的功能,但我不确定这是否会使String.intern()过时 我知道这个JVM功能需要G1垃圾收集器,这对很多人来说可能不是一个选项,但是假设有人使用G1GC,JVM自动执行重复数据消除与手动执行intern字符串有什么区别/优势/劣势(一个明显的优点是不必通过调用intern())来污染代码。) 考虑到Oracle可能会使用此功能使G1GC成为java 9中的默认GC,这一点尤其有趣。如果您有1000个不同的字符串对象,所
String.intern()
过时
我知道这个JVM功能需要G1垃圾收集器,这对很多人来说可能不是一个选项,但是假设有人使用G1GC,JVM自动执行重复数据消除与手动执行intern
字符串有什么区别/优势/劣势(一个明显的优点是不必通过调用intern()
)来污染代码。)
考虑到Oracle可能会使用此功能使G1GC成为java 9中的默认GC,这一点尤其有趣。如果您有1000个不同的字符串对象,所有对象都具有相同的内容,JVM可以使它们在内部共享相同的
char[]
。但是,您仍然有1000个不同的String
对象
使用intern()
,您将只有一个String
对象。因此,如果您关心内存节省,intern()
会更好。它将节省空间和GC时间
然而,上次我听说,
intern()
的性能并没有那么好。您最好拥有自己的字符串缓存,甚至使用ConcurrentHashMap
…但您需要对其进行基准测试以确保。我想介绍另一个与目标受众相关的决策因素:
- 对于一个系统集成商来说,系统由许多不同的库/框架组成,其容量很低,无法影响这些库的内部开发,如果内存存在问题,StringDuplication可能是一个快速的赢家。它会影响JVM中的所有字符串,但G1只会使用空闲时间来完成。在进行重复数据消除时,您甚至可能会进行调整通过使用另一个参数(StringDeduplicationGetThreshold)计算重复数据
- 对于分析自己代码的开发人员来说,String.intern可能更有趣。需要仔细检查域模型,以确定是否调用intern以及何时调用。根据经验,当您知道字符串将包含一组有限的值时,可以使用intern,例如枚举集(即国家名称、月份、星期几…)
- 您是否可以完全控制GC的选择?例如,在GUI应用程序中,使用串行GC仍然有很好的理由。(该过程的总内存占用量要低得多-对于一个中等复杂的应用程序,想想400 MB vs~1 GB,并且更愿意释放内存,例如在使用率出现短暂峰值后)。因此,您可以选择该选项,或者让您的用户选择。(如果堆仍然很小,那么暂停应该不是什么大问题)
- 您对代码有完全的控制权吗?G1GC选项非常适合您无法编辑的第三方库(和应用程序!)
String.intern
可以对String
对象本身进行重复数据消除,而G1GC必须只能对其私有char[]
字段进行重复数据消除
第三个考虑因素可能是CPU使用情况,比如对笔记本电脑电池寿命的影响可能会引起用户的关注。G1GC将运行一个额外的线程,专门用于消除堆的重复。例如,我在运行Eclipse时使用了这个线程,发现它在启动后会导致CPU活动的初始阶段增加(想想1-2分钟)但是,它解决了一个较小的堆“正在使用”,并且没有明显的CPU开销(仅仅是任务管理器的眼珠)或此后的速度减慢。因此,我认为一定比例的CPU核心将用于重复数据消除(在?之后?)高内存波动期间。(当然,如果到处调用String.intern,可能会有相当的开销,它也会以串行方式运行,但是…)
您可能不需要到处进行字符串重复数据消除。可能只有某些代码区域:
- 真正影响堆的长期使用,和
- 创建高比例的重复字符串
String.intern
,代码的其他部分(可能创建临时或半临时字符串)不会为此付出代价
最后,一个用于Guava实用程序的快速插头:,它:
为其他不可变类型提供与String.intern()
等效的行为
您也可以将其用于字符串。内存可能是(并且应该是)你的最高性能关注,所以这可能不经常适用:但是当你需要挤压某个热点区域的每一个速度,我的经验是,基于java的弱引用HasMeP解决方案运行的速度比JVM C++实现的代码<> String。,即使在优化了jvm选项之后。(还有一个好处:你不需要调整jvm选项以适应不同的输入。)——但不管怎样,结论总是一样的:你.Should.Not.Care.sorry,不应该关心什么?关于使用哪一个(意味着它们是等效的)或关于新功能(意味着它没有那么有用)??含义:不用再想就可以使用
String
类。好问题。这些特性添加到JVM中是一个提示,提示开发人员将重点放在编码而不是内存管理上。您不应该使用String.intern()
或System.gc()
——让虚拟机完成它的工作。@DavidConrad在完整的引用中克努斯实际上量化了他的建议:“我们应该忘记小效率,比如说