【问题标题】:How does Java optimize function calls and variable usage?Java如何优化函数调用和变量使用?
【发布时间】:2016-12-22 14:59:37
【问题描述】:

SPOILER - 该问题包含在线法官问题的解决方案。

我在 LeetCode 上解决了this 的问题。

我的solution 被接受并且优于 92% 的提交。为了优化我的解决方案,我做了一个特别的改变。修改后的解决方案可以在here 找到。我所做的唯一更改如下:

我没有每次都使用s.length()(特别是19次),而是创建了一个新变量int len=s.length()

我预计性能会有所提高,但新解决方案优于“仅 69% 的提交”,即性能下降 25%。此外,虽然第一种情况下所有测试用例都需要 1ms,但第二种情况下需要 2ms,虽然差异不大,但我完全没有预料到。这可能是什么原因?

【问题讨论】:

  • s.length() 已知是常数; int len 不一定是常数,因此它可能必须不断重新获取值。
  • 你可以改用final int len,这告诉编译器你的值是一个常数,它可以进一步优化
  • 请不要链接到外部站点获取源代码。最好将代码的相关部分包含在您的问题中。
  • 您要询问的所有代码都应包含在文本中您的问题中。不接受引用其他地方托管的资源来传达您问题的基本要素。
  • 您多久试用一次改进版?在 cpu 时间方面有多大差异? 92% 和 69% 之间的差异可能只是测试系统上的随机 CPU 峰值。

标签: java algorithm compiler-optimization


【解决方案1】:

您的一般问题的一般答案是:视情况而定

你看,真正的优化不是由 Java 编译器完成的。 java-to-bytecode 编译器只使用了一组非常有限的已知优化技术;例如常量折叠(将 5*3 变成 15)。

真正的“物有所值”发生在运行时,由即时编译器完成。你必须明白,这项技术可能经过 15 年以上的深入研究。因此,根本无法用一个简单、全面的答案告诉您 JIT 的能力。或者它到底在做什么。本质上,它观察你的代码在做什么;在有意义的地方,它将字节码转换为机器码。有时,它甚至会重做翻译;当它发现“事情”发生了变化时。

请参阅 herethere 了解我在说什么。

当然,正如一些 cmets 指出的那样:您完全没有了解“评判系统”是如何进行基准测试的。而且您知道,使用 Java 进行基准测试hard。因此,如果您真的对您的代码感到好奇:退后一步,创建您的自己的测量套件(基于我上面链接中的那些最佳实践)并测量您自己的数据点。

【讨论】:

  • 与这个答案大致相关的关键点可能是:你不知道这个网站是如何测量时间的。他们可能执行代码一次,这并不能告诉你任何事情。如果他们使用不同的输入重复运行代码,并允许 JIT 启动,并在这样的预热阶段之后进行时间测量,那么结果很可能会大不相同。
  • 在阅读您的评论之前,我正在添加关于该主题的另一段 ;-)
【解决方案2】:

如果你开始阅读 Java 字节码,javap -p -s -v -c -constants Something.class 命令会变得非常方便。

通常在s.length() 场景中,您调用不同的类,创建不同的堆栈框架,用于评估该调用。

int x = s.length() 场景中,您执行相同的调用,但您执行额外的调用以将整数存储在堆栈帧中的一个帧存储位置。

这意味着重用存储的调用会根据许多混杂因素变得更快或更慢。

  1. 如果您要多次调用s.length(),则在s.length() 编译或内联到调用堆栈后,您会更早触发热点调用优化的限制,从而加快执行速度。
  2. 如果s.length() 非常缓慢或复杂,或者您只打算调用它几次,那么缓存该值可能会提供更快的执行速度,因为热点可能会拒绝优化调用。

这些当然是我在逆向/组装/阅读代码后开发的经验法则,就像所有好的经验法则一样,在特定情况下几乎没有用。 如果您有特定的场景,请进行基准测试。 在观察 #1 和 #2 中都有很多“如果”,而且大多数时候我不知道哪些没有在发挥作用基准测试。

考虑到这一点,通常,尤其是在任何热点触发优化之前,方法中字节码操作的数量越少,通常运行速度就越快。此外,堆栈帧(优化前)比您可能倾向于认为(CPU 方面)更昂贵,但热点在降低最频繁使用调用的成本方面做得很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多