我正在研究基于Scala的分析系统(http://www.hiringthing.com),我发现我经常问自己以下问题.给定一个没有副作用的"纯"函数,如果我用相同的输入击中该函数两次,我可以期望编译器重用第一次运行时生成的值,还是会再次遍历所有代码.换句话说,下面的第一个例子比第二个更有效吗?
def add(x: Int, y: Int) = x + y * 10000000000
val a = add(1,2)
do_something(a)
do_another_thing(a)
Run Code Online (Sandbox Code Playgroud)
与
def add(x: Int, y: Int) = x + y * 10000000000
do_something( add(1,2) )
do_another_thing( add(1,2) )
Run Code Online (Sandbox Code Playgroud)
如果编译器确实可以优化第二种情况,那么函数的复杂性是否有限制?
我想做的是为了编程方便,避免多次运行某些数学重函数...
谢谢
从我所看到的,Scala编译器根本没有优化它.如果JVM可以确定结果不会改变,那么JVM可能通常没有好的方法可以知道.
所以,一般来说,如果它是一个微不足道的计算,它没有什么区别,因为它是微不足道的,并且因为JVM可以发现它只需要做一次.如果它很复杂,并且速度至关重要,val a =除非你有基准测试证明JVM在这种情况下足够智能,否则你应该使用该方法.
请注意,有时放置val感觉很尴尬.有两种方法可以解决这个问题.首先,请注意几乎任何东西都可以用大括号中的等效语句替换,因此异常可能比您想象的少.此外,此方法在某些情况下可能有用:
def reuse[A,B](a: A)(f: A => B) = f(a)
reuse(add(1,2))( a => { do_something(a); do_another_thing(a)})
Run Code Online (Sandbox Code Playgroud)
scala编译器不会尝试优化对函数或方法的任何调用,除非您专门使用@inline注释(甚至不是gauranteed).也就是说,JVM,特别是Hotspot JIT编译器,几乎肯定能够在您的示例中内联调用"添加",然后就可以删除生成的common-subexpressions.
一如既往在询问有关性能和编译器优化的问题时,如果没有广泛的专业基准测试,则不应将答案视为福音.过去的表现并不是未来回报的保证.内容可能在运输过程中解决 如果四小时后肿胀持续,请去看医生.所有型号满18岁.
| 归档时间: |
|
| 查看次数: |
407 次 |
| 最近记录: |