编写以下程序是为了检查Scala中的递归深度可以深入到我的机器上。我假设它主要取决于分配给该程序的堆栈大小。但是,在计算了递归的最大深度(在出现时捕获异常)并尝试模拟此深度的递归后,我得到了奇数输出。
/usr/lib/jvm/java-8-oracle/bin/java
Recursion depth on this system is 7166.
sumArrayRec = 25672195
Process finished with exit code 0
结果因程序的执行而异。
其中一个是理想的输出:
/usr/lib/jvm/java-8-oracle/bin/java
Recursion depth on this system is 8129.
Exception in thread "main" java.lang.StackOverflowError
at RecursionTest$.goFrom$1(lab44.scala:6)
at RecursionTest$.goFrom$1(lab44.scala:6)
at RecursionTest$.goFrom$1(lab44.scala:6)
(...)
at RecursionTest$.goFrom$1(lab44.scala:6)
at RecursionTest$.goFrom$1(lab44.scala:6)
Process finished with exit code 1
然而,我得到的第二个可能的输出表示错误:
println("sumArrayRec = " + sumArrayRec((0 until recDepth).toArray))
我没有观察到他们的任何依赖或关系,我只是第一次获得,其他时间获得第二次
所有这些都引导我提出以下问题:
当我将println("sumArrayRec = " + sumArrayRec((0 until recDepth - 5000).toArray))
更改为
<Command Name="ShutDown">
<ListenFor>Shut down</ListenFor>
<Navigate/>
</Command>
,更不用说,行为保持不变。
答案 0 :(得分:1)
recurseTest
和sumArrayRec
将不同的金额推送到堆栈。 recurseTest
基本在每次调用时为堆栈添加2个整数,而sumArrayRec
正在添加3个整数,因为您有elms(i)
调用,可能更多添加/ ifelse (更多说明)。由于JVM正在处理所有这些问题,因此很难说清楚它的目的是将这一点与您需要知道的内容混淆。此外,谁知道JVM在幕后做了哪些优化,这些优化可以极大地影响从每个方法调用创建的堆栈大小。在多次运行中,由于系统时序等原因,您可以获得不同的堆栈深度,也许jvm会在程序运行的短时间内优化,也许它不会被激活,它可能是非确定性的这种情况。如果您事先运行了一些预热代码,可能会使您的测试更具确定性,那么任何优化都将会或不会发生。你应该考虑使用类似JMH的东西进行测试,这将有助于确定性。
附注:您也可以使用-Xss2M
手动更改堆栈大小,这对于SBT的使用很常见。