Java 8引入了String Deduplication,可以通过使用// no 'using namespace TAXCONSTANTS;'
int main()
{
taxPayer payers[TAXCONSTANTS::SIZE];
...
}
选项启动JVM来启用,允许通过引用类似的-XX:+UseStringDeduplication
对象而不是保留重复来保存一些内存。当然,它的有效性因程序而异,取决于String
的使用情况,但我认为可以肯定地说,对于大多数应用程序(如果不是全部)而言,它可以被认为是有益的让我感到惊讶很少的事情:
为什么默认情况下不启用?是因为与去重复相关的成本还是因为G1GC仍然被认为是新的?
是否存在(或可能存在)您不想使用重复数据删除的边缘情况?
答案 0 :(得分:23)
字符串重复数据删除可能有害的情况包括:
(第二种情况不是关于在第一个GC循环中不能存活的字符串。对于GC甚至尝试来重复删除它知道的字符串是没有意义的是垃圾。)
我们只能推测为什么Java团队默认情况下没有开启重复数据删除,但他们处于更好的位置,可以就此做出理性(即基于证据的)决策。我的理解是,他们可以访问许多大型实际应用程序,用于基准测试/尝试优化的效果。他们也可能与许多合作伙伴或客户组织建立了深入的联系,这些组织具有类似的大型代码库和对效率的关注......他们可以询问有关哪些优化真正起作用的信息。
1 - 这取决于print(final)
>>> [(0, 1), (0, 6), (0, 7), (1, 3)]
的值
JVM设置。默认为3意味着(大致)字符串必须存在3个次要集合或要考虑重复数据删除的主要集合。但无论如何,如果一个字符串被删除,然后很快就会发现无法访问,那么该字符串的重复删除开销将无法偿还。
如果您在考虑何时应该考虑启用重复数据删除,我的建议是尝试一下,看看它是否有助于基于每个应用程序。但是你需要做一些应用程序级的基准测试(这需要付出努力!)以确保重复数据删除是有益的......
仔细阅读JEP 192也可以帮助您理解问题,并判断它们如何适用于您的Java应用程序。
答案 1 :(得分: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
两个字符串如何连接是一个运行时决定。它可能仍然是一个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
}
默认为:
MH_INLINE_SIZED_EXACT
答案 2 :(得分:0)
在javaperf咨询公司,我们开发了一个自动程序,该程序可以自动对源代码执行更正。实际上,不再有任何重复的字符串。更正规则将应用SonarQube的建议并计算变量名,以使它们在代码中保持可读性。自动化还考虑了已经用于避免名称冲突的其他变量。