Java 递归对服务器有什么影响?

Java 递归对服务器有什么影响?,java,recursion,websphere,Java,Recursion,Websphere,我听说在服务器上运行递归代码会影响性能。这句话的正确性如何?递归方法是否应该作为最后手段使用?一个没有结束的编程错误的递归对机器有负面影响,消耗越来越多的资源,并在最坏的情况下威胁整个系统的稳定性 否则,递归就像循环和其他构造一样是完全合法的工具。它们对性能本身没有负面影响 要讨论性能,您必须讨论非常具体的场景。适当地使用递归就可以了。如果使用不当,可能会导致堆栈损坏,或者使用过多堆栈。如果您以某种方式获得了一个递归的tailcall而没有终止(通常是:一个bug,比如尝试遍历循环图),则尤其如

我听说在服务器上运行递归代码会影响性能。这句话的正确性如何?递归方法是否应该作为最后手段使用?

一个没有结束的编程错误的递归对机器有负面影响,消耗越来越多的资源,并在最坏的情况下威胁整个系统的稳定性


否则,递归就像循环和其他构造一样是完全合法的工具。它们对性能本身没有负面影响

要讨论性能,您必须讨论非常具体的场景。适当地使用递归就可以了。如果使用不当,可能会导致堆栈损坏,或者使用过多堆栈。如果您以某种方式获得了一个递归的tailcall而没有终止(通常是:一个bug,比如尝试遍历循环图),则尤其如此,因为它甚至不会破坏堆栈(它将永远运行,占用CPU周期)


但是,如果做对了(并将深度限制在合理的范围内),就可以了。

递归可能会比等效的迭代解决方案消耗更多的内存,因为后者可以优化为只占用严格需要的内存,但递归会保存堆栈上的所有局部变量,因此,占用的空间比严格需要的稍多。这只是内存有限的环境中的一个问题(这种情况并不罕见),对于可能非常深入的递归(几十个递归分支最多占用几百个字节,不会对服务器的内存占用造成明显的影响),因此“最后的手段”是过度的

但是,当分析表明占用空间的影响很大时,您肯定可以执行的一个优化重构是——几十年前学术文献中的一个热门话题,但通常不难手工完成(特别是如果您将所有方法(递归或其他)保持在合理的小范围内,这是您应该做的;-)

我听说在服务器上运行递归代码会影响性能。这有多真实 声明

的确,它会影响性能,就像创建变量、循环或执行几乎所有其他东西一样

如果递归代码不好或不受控制,它将像不受控制的while循环一样消耗系统资源

递归方法应该作为最后手段吗


不可以。它可以作为第一种手段,很多时候编写递归函数会更容易。取决于你的技能。但要明确的是,递归没有什么特别有害的

在服务器上运行任何代码都会影响性能。服务器性能通常首先会受到存储I/O的影响,因此在“服务器性能”级别上,很难看到讨论的一般算法策略问题。

当您必须编写算法时,递归是一种选择工具。当您必须处理像树或图这样的重复数据结构时,它也比迭代容易得多。如果(作为经验法则)你可以将复发深度评估到不太大的程度,只要你不忘记结束条件,这通常是无害的

大多数现代编译器能够优化某些类型的递归调用(在内部用非递归等价物替换它们)。尾部递归特别容易,即当递归调用是返回结果之前的最后一条指令时

但是,存在一些特定于Java的问题。底层JVM不提供任何类型的goto指令。这设置了编译器可以执行的操作的限制。如果它是一个函数内部的尾端递归,则可以用该函数内部的简单循环来替换,但是如果终端调用是通过另一个函数完成的,或者如果多个函数反复调用另一个函数,则在以JVM字节码为目标时,这将变得非常困难。SUN JVM不支持尾部调用优化,但要改变这一点,IBM JVM支持尾部调用优化


对于某些语言(如LISP或Haskell等函数式语言),递归也是编写程序的唯一(或更自然)方法。在基于JVM的函数式语言(如Clojure或Scala)上,缺少尾部调用优化是一个问题,它会导致类似Scala的解决方法。

深度递归可能会导致堆栈溢出,这很糟糕。要小心,如果你需要的话,很难再起床了。小的、可管理的工作更容易处理和并行化

尾部-递归也是一种选择。归结起来就是:只需将返回的
结果作为可变引用传递给递归方法的参数即可。这样堆栈就不会爆炸。更多关于和。

嗯?您还可以编写一个讨厌的for循环,这也会使服务器过载。服务器过载=错误。如果可以,请配置文件。websphere中的任何内容都会看到kay。我打赌您是在收到StackOverflower错误后来到这里的;)别开玩笑了:有些情况下迭代实现更好。但只要没有真正的理由,就不要考虑优化。@sfussenegger不,我没有遇到错误,只是想在递归似乎合适的地方实现一些新功能,并希望对该主题进行一些澄清。感谢您的快速响应。嗯,如果编译器没有意识到递归尾调用来优化堆栈,它会破坏堆栈。你不能真正使用太多堆栈,因为一旦创建线程,堆栈的大小就固定了。因此,您只能通过使用多个线程来使用多个堆栈。有关有趣的分析,请参阅将变量放入堆栈不会消耗任何额外内存。堆栈大小是在线程创建时分配的,不会增长。@sfussenger:1:(我认为)整个堆栈内存直到需要时才提交,只是保留了,这意味着在递归过程中可能需要提交额外的内存。2.当你到达m