【发布时间】:2012-01-20 05:36:16
【问题描述】:
在递归调用期间,获取或计算 Java 中可用的剩余堆栈内存的最佳方法是什么?
(我正在尝试对深度递归调用进行分段,以尽可能多地使用堆栈(为了提高速度性能),但不会遇到堆栈溢出。
我已经做了一个“堆”版本,它带来了速度性能开销,这就是我做这个优化的原因。)
【问题讨论】:
在递归调用期间,获取或计算 Java 中可用的剩余堆栈内存的最佳方法是什么?
(我正在尝试对深度递归调用进行分段,以尽可能多地使用堆栈(为了提高速度性能),但不会遇到堆栈溢出。
我已经做了一个“堆”版本,它带来了速度性能开销,这就是我做这个优化的原因。)
【问题讨论】:
你需要它做什么?好奇而已?度量单位是什么 - 字节或递归调用的数量?
您总是可以进行无限递归调用,捕获StackOverflowError 并计算堆栈帧数
【讨论】:
没有办法以便携的方式做到这一点。
这不仅是特定于操作系统的,实际上堆栈的最大大小受多种约束(ulimit -c、可用虚拟内存量、-Xss 和-XX:ThreadStackSize 设置等)。这使得很难知道哪个约束将首先受到影响,即使您可以可靠地测量到目前为止已经消耗了多少堆栈空间。
【讨论】:
嗯。如果您担心,可以始终将深度计数器作为递归的一部分。
【讨论】:
我会编写减少递归的方法。通常有一些方法可以减少(或不)递归调用。
如果您递归地对列表求和,将第一个值添加到其余值的总和中,这将调用深度为 N。但是,如果您将列表切成两半并对值求和。 (如果列表中只有一个则返回值)递归深度为log2(N)。
【讨论】:
我很惊讶迭代方法的性能较差。通常,由于方法调用的开销,递归方法会更慢。如果您的算法可以实现为尾递归,则几乎可以肯定它作为迭代实现会更快。你能告诉我们更多关于你真正想做的事情吗?也许性能上的差异不仅仅是为了递归而切换迭代。这是来自一些CS lecture notes 的示例,它引用了计算斐波那契数的递归方法,即 O(2^n),而迭代方法是 O(n)。我相信(尽管我没有尝试过)可以编写一个 O(n) 的递归斐波那契数生成器。
编辑:
最后一个想法。恕我直言,最好使用没有堆栈溢出问题的较慢方法,而不是引入尝试确定您即将溢出堆栈并具有一些回退机制来避免它的所有复杂性。
【讨论】: