Java如何优化函数调用和变量使用?
扰流板-该问题包含在线法官问题的解决方案 我解决了关于LeetCode的问题 我的申请被接受,超过92%的申请。为了优化我的解决方案,我做了一个特别的更改。可以找到修改后的解决方案。我所做的唯一更改如下: 我没有每次使用Java如何优化函数调用和变量使用?,java,algorithm,compiler-optimization,Java,Algorithm,Compiler Optimization,扰流板-该问题包含在线法官问题的解决方案 我解决了关于LeetCode的问题 我的申请被接受,超过92%的申请。为了优化我的解决方案,我做了一个特别的更改。可以找到修改后的解决方案。我所做的唯一更改如下: 我没有每次使用s.length(),而是创建了一个新变量int len=s.length() 我原以为性能会提高,但新的解决方案比“只有69%的提交”更好,即性能下降25%。此外,虽然在第一种情况下所有测试用例都需要1ms才能通过,但在第二种情况下需要2ms,虽然差异不大,但这是我完全没有预料
s.length()
,而是创建了一个新变量int len=s.length()
我原以为性能会提高,但新的解决方案比“只有69%的提交”更好,即性能下降25%。此外,虽然在第一种情况下所有测试用例都需要1ms才能通过,但在第二种情况下需要2ms,虽然差异不大,但这是我完全没有预料到的。这背后的原因可能是什么?对你的一般问题的一般回答是:这取决于 你看,real优化不是由Java编译器完成的。java到字节码编译器只使用非常有限的一组已知优化技术;例如,不断折叠(将5*3变为15) 实时编译器在运行时执行real“bung for The buck”。你必须明白,大概有15年多的时间对这项技术进行了深入研究。因此,根本没有办法用一个简单、全面的答案告诉您JIT能做什么。或者它到底在做什么。本质上,它观察代码在做什么;在有意义的地方,它将字节码转换成机器码。有时,它甚至会重做它的翻译;当它发现“东西”变了 看一看或看一看我在说什么
当然,正如一些评论所指出的:对于“评判系统”是如何进行基准测试的,您根本没有任何见解。你知道,用Java做基准测试是。因此,如果你真的对你的代码感到好奇:退一步,创建你自己的度量套件(基于我上面链接中的那些最佳实践)并度量你自己的数据点。如果你开始阅读Java字节码,命令
javap-p-s-v-c-constants Something.class
将非常方便
通常在s.length()
场景中,对不同的类执行调用,创建不同的堆栈帧,用于评估该调用
在int x=s.length()
场景中,执行相同的调用,但执行另一个调用以将整数存储在堆栈帧中的一个帧存储位置
这意味着基于许多混杂因素,重用存储的调用会变得更快或更慢
s.length()
,那么在编译s.length()
或将其内联到调用堆栈之后,您可能会更早地触发hotspot调用优化的限制,从而导致更快的执行s.length()
速度太慢或太复杂,或者您只需要调用它几次,那么缓存该值可能会提供更快的执行速度,因为hotspot可能会拒绝优化调用考虑到这一点,通常,尤其是在任何热点触发优化之前,方法中字节码操作的数量越少,通常运行得越快。此外,堆栈帧(预优化)比您可能倾向于认为的(CPU方面)更昂贵,但hotspot在降低最频繁使用的调用的成本方面做了大量工作。
s.length()
已知为常数int len
不一定是常量,因此它可能需要不断重新获取值。您可以使用final int len
来代替,这会告诉编译器您的值是常量,它可以进一步优化。请不要链接到外部站点获取源代码。最好将代码的相关部分包含在问题中。您想询问的所有代码都应包含在问题文本中。引用托管在其他地方的资源无法传达问题的基本要素。您多久尝试一次改进的版本,在cpu时间方面有多大差异?92%和69%之间的差异可能只是测试系统上的随机CPU峰值。与此答案大致相关的关键点可能是:你不知道这个网站是如何测量时间的。他们可能只执行一次代码,但这并没有告诉您任何事情。如果他们使用不同的输入重复运行代码,并允许JIT启动,并在预热阶段之后进行时间测量,那么结果很可能会有很大的不同。在阅读您的评论之前,我刚刚添加了关于该主题的另一段;-)