在Java中,递归调用过程中获取或计算剩余可用的堆栈内存,最好的方法是什么?
(我正在尝试对深度递归调用进行分段,并尽可能使用堆栈以提高速度性能,但避免出现堆栈溢出。我已经完成了一个“堆”版本,但带来了速度性能开销,这就是为什么我正在进行此优化的原因。)
无法以便携的方式完成此操作。
不仅如此,实际上栈的最大大小受到多个限制的约束(例如:ulimit -c
、可用虚拟内存的数量、-Xss
和-XX:ThreadStackSize
设置等),这使得很难知道哪个限制会首先达到,即使您可以可靠地测量到目前已使用了多少堆栈空间。
我会编写一个不那么递归的方法。通常有办法可以减少(或者不需要)递归调用。
如果你递归地对列表求和,将第一个值加到其余部分的总和中,这将导致深度为N的调用。然而,如果你把列表分成两半并求和。(如果列表中只有一个值,则返回该值),递归深度就是log2(N)。
我很惊讶迭代方法的性能比递归方法差。通常由于方法调用的开销,递归方法会更慢。如果您的算法可以实现为尾递归,则几乎肯定作为迭代实现会更快。您能否告诉我们更多关于您实际要做什么的信息?也许性能差异更多地是算法上的问题,而不仅仅是将迭代换成递归。这里有一个例子来自一些CS讲义,它引用了一种递归方法来计算斐波那契数列,其时间复杂度为O(2^n),而迭代方法的时间复杂度为O(n)。我相信(虽然我没有尝试过),可能会编写一个递归斐波那契数生成器,其时间复杂度为O(n)。
编辑:
最后一点想法。在我看来,使用一个速度较慢但没有堆栈溢出问题的方法要好得多,而不是引入所有复杂性来确定您即将溢出堆栈,并具有一些回退机制以避免它。