scala - 为什么在 Maven Surefire 中指定 Xss 会使 ScalaTest 运行速度提高一倍?
问题描述
我有一个 FunSuite 单元测试测试高度递归(非尾)Scala 函数。如果我将下面的行添加到我的 pom.xml Surefire 中<configuration>
,它的运行速度会提高一倍。
<argLine>-Xss1024k</argLine>
我指定什么值并不重要,除非我指定一个非常低的值,例如 -Xss256k,我会得到预期的 StackOverflowException。否则,我可以将它设置在 512k 到 512m 之间的任何位置,并且执行时间都是一样的。但是,如果我从 pom.xml 中完全删除该行,则执行时间会加倍。
为什么会这样?
解决方案
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
推荐阅读
- python - 在 Python 中对 CSV 文件进行训练测试拆分
- php - 使用 GLOB 排除多个目录
- excel-formula - 如何回查反对者单元格和数据验证列表?
- python - Kivy 不显示图像
- c# - 使用 C# 访问 COM 对象中的隐藏动态属性
- swift - Swift:使用命令行工具将 .strings 文件解析为 .csv 文件
- mercurial - Mercurial:执行推送后如何恢复到上一个版本
- php - Include git commit information inside a project
- java - Java 10 可执行文件在安装后不会执行
- python - 使用 Django 表单编辑图像字段