拳击是否会导致性能问题?

5

我正在开发一个项目,它能够将代码转换为Java语言。我们使用的框架是xtext,在生成的代码中广泛使用了装箱。

具体而言,如果你有如下语句:

int i = 1;
int j = 2;
int k = i + j;

然后编译后的代码如下所示:
IntegerExtensions.operator_plus(((Integer)i), ((Integer)j))

现在,在我正在处理的项目中,某些情况下特定的基本二进制操作将会非常常见(尤其是增量和比较)。
我的问题是:这是否会对性能造成问题,或者JIT(或类似的智能JVM功能)会简单地意识到正在发生什么并解决所有问题?
请在发布之前阅读:我不希望得到回复说“你不应该关心,让它易读”。这段代码是生成的,我只是不关心生成代码的可读性。我关心的是我们不会因此受到重大的性能损失。
谢谢

当你说编译代码时,是指编译到你的框架中还是编译成字节码? - corsiKa
装箱比不装箱更昂贵。这有关系吗?(这是唯一真正的问题。)嗯,“这取决于”...还有,为什么编译后的代码看起来像那样? :) 有一个iadd本地java字节码... - user166390
@glowcodeer:当我说编译代码时,我的意思是将我的语言编译成.java文件。 - Jeff
@pst:我不确定为什么代码看起来像那样,但我假设在一般情况下有某种原因。至于“它是否重要?”,这实际上不是问题——问题是“它是否总是更昂贵?”请参见我关于即时编译的提及以及我对John答案的评论。 - Jeff
@Jeff 具体答案仍然是:“很可能是”,而一般答案是“取决于情况”。仅仅因为不一定会创建新对象并不意味着它在字节码或 JIT 代码中具有相同的路径。找到一种理想病态的情况,可以有效地将其 JIT 掉——假设存在这样的情况——并没有帮助。只有复制真实使用情况的性能分析才能“正确”回答这个问题。 - user166390
4个回答

4

这实际上可能会产生影响。当进行Integer类型转换时,它将使用Integer.valueOf(int n)方法将int转换为Integer。该方法将检查该值是否在缓存范围内(-128到127),如果不是,则会创建new Integer(n)

影响的程度可能很大或很小,您需要自行测试。


那么 JIT 或类似的东西有没有可能意识到装箱是完全无意义的并完全摆脱它呢?这些盒子非常频繁地发生,在基本相同的情况下,并且不会停留很长时间,我真的希望 JVM 能够为我完成工作。 - Jeff
据我所知,JIT 不会绕过装箱操作(如果它能够这样做,那将是一个非常强大的运行时优化算法)。 - Kevin Day
2
使用-XX:+EscapeAnalysis可以消除创建的自动装箱对象。实际上,我从未见过Sun/Oracle JVM丢弃对象创建。在担心这个问题之前,最好先通过分析应用程序来确定它是否重要。 - Peter Lawrey

3
说它会“导致性能问题”取决于你如何定义问题。而你所称之为问题可能取决于代码将要解决的问题类型。
这个答案中有一节总结了这个问题,并提供了一个链接到自动装箱指南的链接,其中提到:

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

这里有一个特定的例子,重点关注int / Integer自动装箱的基准测试

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

简单答案:每个装箱需要15纳秒。


3
我从经验中得到了几点观察结果:
  1. 总的来说,装箱确实会降低应用程序的性能。这些性能损失的大小取决于实现算法的性质。是否值得修复以及何处修复,只有分析器和您的预期成本效益比才能告诉您。

  2. 总的来说,装箱确实会增加应用程序的内存使用量。就我而言,这非常重要——可能比性能更重要。

    在 Java 中,一个 int 占用 4 到 8 字节(取决于 JVM 实现)的内存,可以表示 32 位的范围。一个 Integer 在 64 位系统上占用 20 到 24 字节的空间——你还需要一个引用。对于处理大型数组的应用程序,这可能会使其内存需求增加四倍(×4)或者更多。

    在这种情况下,装箱可能是"奏效"与"无法奏效"之间的关键因素——在给定的计算机上,可使用的内存是有限的。此时性能甚至不被讨论,尽管内存极度匮乏的应用程序通常也会更慢。

话虽如此,对象确实具有一个有用的优点:使用 null 可以本地表示"不存在值"。


我认为,尽管内存可能是一个问题,但垃圾回收器应该能够处理这个问题。我正在处理的情况下,对象被装箱的时间非常短,因此垃圾回收器应该能够非常快速地丢弃产生的对象。持久化状态仍然保留为int类型,只有在需要执行某些操作时才会进行装箱。 - Jeff

1

简单来说:测试一下。

制作一个简单示例的两个版本并测量所需时间。然后,您就会知道性能上的确切差异以及是否负担得起。


2
是的,我们应该自己谷歌和测试一切。我们不需要在SO上问问题。 - jgauffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接