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

2024-06-10 20:08:41 发布

您现在位置:Python中文网/ 问答频道 /正文

人们说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实现,是否也必须做出同样的牺牲?还要牺牲什么吗?在


Tags: thetolambdaorgnodehttp堆栈jvm
3条回答

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

我要特别指出的是:

The down side of course is that if you have to debug or profile optimized code, be prepared to deal with call stacks that look like they’re missing a few frames.

我认为JVM也不太可能避免这种情况。在

考虑到,在请求尾部调用优化的情况下,JIT应该假定它是必需的以避免堆栈溢出,这不是在调试构建中可以关闭的。如果它们在您进入有趣的部分之前崩溃,那么它们对调试没有多大用处。“优化”实际上是一个永久性的特性,也是受其影响的堆栈跟踪的问题。在

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

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

是的,通常情况下,实现TCO将阻止您获得完整的堆栈跟踪。这是不可避免的,因为TCO的全部目的是避免创建额外的堆栈帧。在

值得注意的是,Clojure有一个非堆栈消耗的“recur”特性,可以绕过当前JVM版本上的这个限制。在

示例:

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

(triangle 1000000 0)

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

相关问题 更多 >