Nin*_*tou 25 java optimization performance java-8
Java 8引入了String Deduplication,它可以通过启动JVM来启用,该-XX:+UseStringDeduplication选项允许通过引用类似String对象而不是保留重复来保存一些内存.当然,它的效果因程序而异,具体取决于使用情况,Strings但我认为一般来说它可以被认为对大多数应用程序(如果不是全部)都有益,这让我对以下几点感到好奇:
为什么默认情况下不启用?是因为与去重复相关的成本还是因为G1GC仍然被认为是新的?
是否存在(或可能存在)您不想使用重复数据删除的边缘情况?
Ste*_*n C 27
字符串重复删除可能有害的情况包括:
(第二种情况不是关于不能在第一个GC循环中存活的字符串.对于GC甚至尝试对它知道是垃圾的字符串进行重复删除是没有意义的.)
我们只能推测为什么Java团队默认情况下没有打开重复数据删除,但他们处于更好的位置,可以对你和我做出理性(即基于证据的)决策.我的理解是他们可以访问许多大型实际应用程序,用于基准测试/尝试优化的效果.他们也可能与许多合作伙伴或客户组织建立了深入的联系,他们拥有类似的大型代码库和对效率的担忧......他们可以询问有关哪些优化真正起作用的信息.
1 - 这取决于StringDeduplicationAgeThreshold
JVM设置的值.默认为3意味着(大致)字符串必须存在3个次要集合或要考虑重复数据删除的主要集合.但无论如何,如果一个字符串被删除然后发现不久之后就无法访问,那么该字符串的重复删除开销将无法偿还.
如果您在考虑何时应该考虑启用重复数据删除,我的建议是尝试一下,看看它是否对每个应用程序有帮助.但是你需要做一些应用程序级的基准测试(这需要付出努力!)以确保重复数据删除是有益的......
仔细阅读JEP 192还可以帮助您理解问题,并判断它们如何应用于您的Java应用程序.
Eug*_*ene 18
我完全明白这不回答这个问题,只是想提一下jdk-9引入了另一个默认启用的优化:
-XX:+ CompactStrings
其中Latin1字符占用一个字节而不是两个(通过char).由于这种变化,String的许多内部方法都发生了变化 - 它们对用户的行为相同,但在内部它们在很多情况下都更快.
同样在Strings通过加号连接两个字符串的情况下,javac将生成不同的字节码.
没有字节码指令将两个字符串连接在一起,因此javac会生成一个
StringBuilder的追加#
在后端.直到jdk-9.
现在字节码委托给了
StringConcatFactory#makeConcatWithConstants
要么
StringConcatFactory#makeConcat
通过invokedynamic字节码指令:
aload_0
1: aload_2
2: aload_1
3: invokedynamic #8, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
8: areturn
Run Code Online (Sandbox Code Playgroud)
两个字符串如何连接是一个运行时决定.它可能仍然是一个StringBuilder,或者它可能是字节数组等的串联.你知道这可以改变,你将获得最快的解决方案.
编辑
我刚刚调试过,看到有很多关于如何附加这些字符串的策略:
private enum Strategy {
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder}.
*/
BC_SB,
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder};
* but trying to estimate the required storage.
*/
BC_SB_SIZED,
/**
* Bytecode generator, calling into {@link java.lang.StringBuilder};
* but computing the required storage exactly.
*/
BC_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
* This strategy also tries to estimate the required storage.
*/
MH_SB_SIZED,
/**
* MethodHandle-based generator, that in the end calls into {@link java.lang.StringBuilder}.
* This strategy also estimate the required storage exactly.
*/
MH_SB_SIZED_EXACT,
/**
* MethodHandle-based generator, that constructs its own byte[] array from
* the arguments. It computes the required storage exactly.
*/
MH_INLINE_SIZED_EXACT
}
Run Code Online (Sandbox Code Playgroud)
默认为:
MH_INLINE_SIZED_EXACT