Java 拳击会导致性能问题吗?

Java 拳击会导致性能问题吗?,java,performance,jit,boxing,xtext,Java,Performance,Jit,Boxing,Xtext,我正在做一个项目,我们正在制作一种编译成java的语言。我们正在使用的框架(xtext)在其生成的代码中大量使用了装箱。 具体来说,如果您有如下声明: int i = 1; int j = 2; int k = i + j; 然后编译的代码如下所示: IntegerExtensions.operator_plus(((Integer)i), ((Integer)j)) 现在,在我正在进行的项目中,在某些情况下,特定的基本二进制操作将非常常见(尤其是增量和比较) 我的问题是:这将是一个性能方面

我正在做一个项目,我们正在制作一种编译成java的语言。我们正在使用的框架(xtext)在其生成的代码中大量使用了装箱。 具体来说,如果您有如下声明:

int i = 1;
int j = 2;
int k = i + j;
然后编译的代码如下所示:

IntegerExtensions.operator_plus(((Integer)i), ((Integer)j))
现在,在我正在进行的项目中,在某些情况下,特定的基本二进制操作将非常常见(尤其是增量和比较)

我的问题是:这将是一个性能方面的问题,还是JIT(或类似智能JVM特性)会仅仅意识到发生了什么并解决所有问题

请在发帖前阅读:我不想收到回复说“你不应该在意,让它可读”。这段代码是生成的,我根本不关心生成代码的可读性。我真正关心的是,我们不会因此受到重大性能影响

感谢您说它会导致性能问题取决于您所说的问题。您所称的问题可能取决于代码将要解决的问题类型

其中有一节对其进行了总结,并提供了指向自动装箱指南的链接,其中提到:

对于科学计算或其他性能敏感的数字代码,不适合使用自动装箱和取消装箱

这里有一个

简单问题:int/Integer类型的自动装箱有多贵

简单的回答:每盒15纳秒

简单地说:测试它


制作一个简单示例的两个版本,并测量所需的时间。然后你就会知道性能的确切差别,如果你能负担得起的话。

这实际上会产生影响。当转换为
Integer
时,它将使用
Integer.valueOf(int n)
方法将
int
转换为
Integer
。此方法将检查值是否在缓存范围(-128到127)内,如果不在缓存范围内,则将创建新的整数(n)


影响的大小可能很大,也可能很小,你必须自己测试一下。

根据我的经验观察到:

  • 装箱通常会降低应用程序的性能。它的显著程度取决于所实现算法的性质。它是否值得修复,它在哪里,只有探查器和您预期的成本效益比才能告诉您

  • 装箱通常会增加应用程序的内存使用。就我而言,这一点非常重要——可能比绩效更重要

    Java中的
    int
    占32位内存的4到8字节(取决于JVM实现)。在64位系统上,
    整数
    将占用20到24个字节,您仍然需要对它的引用。对于处理大型阵列的应用程序,它的内存需求很容易达到原来的四倍(x4),甚至更糟

    在这种情况下,装箱可以区分“它工作”和“它不工作”——给定的计算机上只有这么多内存。虽然内存不足的应用程序通常也会比较慢,但性能甚至没有被讨论


  • 这就是说,对象确实有一个有用的优势:有一种本机方式可以通过使用
    null

    来表示“不存在值”。当你说编译代码时,你是指编译到框架中还是编译到字节码中?装箱比不装箱更昂贵。这有关系吗?(这是这里唯一真正的问题)嗯,“这要看情况了”。。。另外,为什么编译后的代码看起来像这样?:)有一个本机java字节码…@Glowcoder:当我说编译代码时,我的意思是从我的语言中提取并编译成.java文件。@pst:我不确定为什么代码看起来像这样,但我假设在一般情况下它背后有某种原因。至于“这有关系吗?”,这实际上不是问题——问题是“它总是更贵吗?”——请看我提到的“及时编译”,以及我对约翰答案的评论。@Jeff具体答案仍然是:“可能是”,一般答案是“视情况而定”。仅仅因为不一定要创建新对象,并不意味着它在字节码或JIT代码中具有相同的路径。找到一个病态的理想病例,在那里它被有效地JIT’ed了——假设这样的病例存在——并没有帮助。只有复制实际使用情况的性能分析才能“正确”回答这个问题。我认为,尽管内存可能是一个问题,但GC应该能够处理这个问题。我正在处理的情况是对象在很短的时间内被装箱,因此GC应该能够很快丢弃生成的对象。持久化状态仍然保持为int,只有当需要发生某些事情时才会被装箱。所以JIT或类似的东西不会意识到装箱是完全没有意义的,并完全摆脱它?在基本相同的情况下,这些情况经常发生,并且不会停留很长时间,我真的希望JVM能够为我完成我的工作。据我所知,JIT不会绕过装箱操作(如果可以的话,这将是运行时优化算法中的一个难题)。使用
    -XX:+EscapeAnalysis
    可以删除创建的自动装箱对象。实际上,我从未见过Sun/Oracle JVM放弃对象创建。在担心应用程序之前,先分析应用程序以确定它是否重要,这样做更有用。是的。我们应该自己搜索和测试一切。我们现在不需要任何令人讨厌的问题。