Clojure JVM 7/8 改进
Rich Hickey 和其他人提到,Clojure 不会从即将为 JVM 7 或 8 计划的 invokeDynamic
中获得显着改进,但会通过尾递归获得性能提升。
尾递归会产生任何影响吗
(fn [...] (recur ...))
?或者
(loop [...] (recur ...))
我不希望它们变得更快,因为编译器可能已经生成了循环结构。
Rich Hickey and others have mentioned that Clojure will not get a significant improvement from the upcoming invokeDynamic
planned for JVM 7 or 8, but will see a performance gain from tail recursion.
Will tail recursion have any effect on
(fn [...] (recur ...))
or
(loop [...] (recur ...))
I don't expect them to get any faster since the compiler probably already generates loop structures.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的例子不会变得更快,因为如果你使用
recur
,你已经告诉编译器你有一个尾递归函数,这允许编译器生成使用goto
的字节代码(就像普通的命令式循环一样)如果 JVM 进行尾调用优化,当然会有一些好处。
您不必再使用 recur (如果您不想),因此您可以编写这样的函数(尾递归函数)
现在 JVM 无法检测尾递归。通过添加尾部调用优化,JVM 能够看到上面的函数,就像您编写了这个一样(因此获得命令式循环速度):
所以这并不是很大的改进,但还有另一种情况,尾部调用优化是真的很棒。
如果您有相互调用的函数(有时甚至超过两个)并且不需要保留在堆栈上(尾递归),那么 JVM 可以优化它们。现在这是不可能的,因为您无法告诉
recur
跳转到其他函数。这是一个例子。如果你尝试使用一个大数字,你会知道你会破坏堆栈,但通过尾部调用优化,你不会。
我所剩无几了。有一个名为
trampoline
的函数已经允许您执行此操作(编程风格稍有变化,并且有一些开销),我将向您推荐一个博客,而不是解释trampoline
正是这样做的:http://pramode.net/clojure/2010/05 /08/clojure-蹦床/
Non your examples will get any faster because if you use
recur
you already tell the compiler that you have a tail recursive function and this allows the compiler to generate byte code that usesgoto
(like a normal imperative loop)There is off course some benefits if the JVM gets tail call optimization.
You wont have to use recur anymore (if you don't want to) so you can write a function like this (a tail recursive function)
Nowdays the JVM is not able to detect the tail recursion. With the addition of tail call optimization the JVM able to see the function above just as if you had written this (and therefore get imperative loop speed):
So that not that great of an improvement but there is another case where the tail call optimization is really great.
If you have functions that call each other (sometimes even more then two) and the do not need to hold on the the stack (are tail recursive) the JVM can optimize them. This is not possible now because you can not tell
recur
to jump to some other function. Here is an example.If you try this with a big number know you will blow the stack but with tail call optimization you won't.
I have on little addition left. There is a function called
trampoline
that allow you do this already (with a little change in programming style and some overhead) Instead of explainingtrampoline
I will refer you to a blog that does exactly that:http://pramode.net/clojure/2010/05/08/clojure-trampoline/