为了实现尾调用优化,jvm必须牺牲什么?

时间:2009-06-17 12:06:19

标签: python clojure jvm stack-trace tail-call-optimization

人们说除了没有尾调用优化的限制之外,clojure实现是优秀的 - 限制jvm而不是clojure实现。

http://lambda-the-ultimate.org/node/2547

有人说,在Python中实现TCO会牺牲

  • 堆栈跟踪转储和
  • 调试规律性。

Explain to me what the big deal with tail call optimization is and why Python needs it

是否必须为实施TCO的jvm做出同样的牺牲?还有什么需要牺牲的吗?

3 个答案:

答案 0 :(得分:6)

虽然不同(因为il指令已经存在),但值得注意的是.Net 64 bit JIT team必须通过额外的努力来尊重所有尾部调用。

我特别提到了评论:

  

当然,缺点是如果你必须调试或配置优化代码,请准备好处理看起来像缺少几帧的调用堆栈。

我认为JVM极不可能避免这种情况。

鉴于此,在请求尾部调用优化的情况下,JIT应该假定它是 required 以避免堆栈溢出,这不是可以在Debug构建中关闭的东西。如果它们在你到达有趣的部分之前崩溃,它们对调试没有多大用处。 “优化”实际上是一个永久性功能,也是受其影响的堆栈跟踪的问题。

值得指出的是,在执行程序员概念上描述/理解为堆栈操作(例如调用函数)的操作时,任何避免创建实际堆栈帧的优化都将导致所呈现的内容之间的断开调试/提供堆栈跟踪和现实时的用户 这是不可避免的,因为描述操作的代码与执行操作的状态机的机制进一步分离。

答案 1 :(得分:2)

工作是underway now以向JVM添加尾调用。有wiki page谈论一些细节。

答案 2 :(得分:0)

是的,通常情况下,实施TCO会阻止您获得完整的堆栈跟踪。这是不可避免的,因为TCO的重点是避免创建额外的堆栈帧。

值得注意的是,Clojure有一个非堆栈消耗的“重复”功能,可以解决当前JVM版本的这种约束。

示例:

(defn triangle [n accumulator] 
  (if 
    (<= n 0)  
      accumulator
      (recur (dec n) (+ n accumulator))))

(triangle 1000000 0)

=> 500000500000     (note stack does not explode here!)