我有一个FunSuite单元测试,用于测试高度递归的(非尾部)Scala函数。如果将下面的行添加到pom.xml Surefire <configuration>
中,它的运行速度将提高一倍。
<argLine>-Xss1024k</argLine>
我指定什么值都没有关系,除了如果我指定了一个非常低的值(如-Xss256k),我会得到预期的StackOverflowException。否则,我可以将其设置为从512k到512m的任意位置,并且执行时间都相同。但是,如果我从pom.xml中完全删除该行,则执行时间将加倍。
为什么会这样?
答案 0 :(得分:1)
JVM规范状态
因为从不直接操纵Java虚拟机堆栈 除了推送和弹出帧外,帧可能是堆分配的。的 Java虚拟机堆栈的内存不需要 连续的。
此规范允许Java虚拟机堆栈为 固定大小或根据需要动态扩展和收缩 计算。如果Java虚拟机堆栈的大小固定, 可以选择每个Java虚拟机堆栈的大小 创建该堆栈时独立运行。
我认为您正在使用的jvm支持动态扩展堆栈。当调用链大于默认的初始堆栈大小时,将从堆中分配堆栈帧。这将导致执行速度变慢。
在您使用参数指定堆栈大小的情况下,堆栈可能在固定大小模式下工作。在这种情况下,将预先分配所有空间,并且不需要新的分配。同样,当您提供较小的堆栈大小时,它不会扩展并抛出StackOverflow,这也表明它正在固定大小模式下工作。
由于您没有提到正在使用的JVM实现,所以这只是基于JVM规范和您的用例的信息所做的假设。
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.2