如何对Raku进行基准测试?

11
我定期关注GitHub Rakudo repository,以查看Rakudo编译器正在进行哪些更改。
有时我会看到提交,其中个别函数的速度提高了一定百分比,像下面的图片一样。

enter image description here

这是评估的工作流程?我很想学习这个,以便了解您的函数的表现,并进一步优化并为Rakudo开发做出贡献。
我在这里这里寻求帮助。我尝试搜索谷歌,但找不到这些信息。我还通过命令行学习了MoarVM分析器--profile选项这里,它生成html输出。需要查找什么?

enter image description here

我不是一个正式的计算机科学家。我理解Tony Hoare所说的名言——“过早优化是万恶之源”,但随着时间的推移,一旦代码编写正确,人们就希望对其进行优化。所以问题来了。


Tony Hoare:Occam的那个家伙!对吧? - librasteve
1个回答

12

我使用--profile来更好地了解瓶颈在哪里。生成的配置文件是一个不错的开始,但当差异变得非常小的时候,在 CPU 使用率方面就不太好了。但是,它在跟踪对象分配方面非常出色,而且较少的对象分配至少可以意味着内存翻转较少(不过并不总是如此,如果对象的寿命非常短)。而使用 --profile 跟踪事物也对优化产生影响,因此海森堡不确定性原理在这里确实适用。

一旦我有了代码的“之前/之后”版本,我会将其作为脚本或单行运行time。我有一堆方便的别名可帮助我完成这个任务:

alias r='time raku -e'
alias rp='raku --profile -e'

我之所以将它作为单独的进程进行,且至少间隔几秒钟,是因为:

  1. 在同一进程中运行多个基准测试会使CPU温度升高,从而导致后面的基准测试变差。
  2. 如果两个基准测试在核心代码中共享某些代码,则后面的基准测试可能会受益于早期基准测试中该代码的内联/JIT编译。

然后我会分别运行每个前后的代码3到5次,并进行一个Nil循环来找出开销。例如:

$ r 'my $a = "42"; Int($a) for ^100000'
real    0m0.244s

$ r 'my $a = "42"; $a.Int for ^100000'
real    0m0.178s

$ r 'my $a = "42"; Nil for ^100000'
real    0m0.154s

然后计算差异:

$ r 'say (244 - 154) / (178 - 154)'
3.75

因此,使用$a.Int的速度大约是Int($a)的3.75倍。这当然可能会启动另一个--profile循环,找出为什么Int($a)速度慢那么多。此外,当我看到无法解释的速度差异时,我使用--profile来确定它是否真正执行我认为它在执行的操作。具体而言,意外的常量折叠有时会让您认为已经找到了最佳优化方案,但实际上您将代码简化为基本上什么都没有做。

希望对你有所帮助。


1
感谢您详细的回答。 - Suman Khanal
1
只是为了补充@elizabeth-mattijsen所说的,我经常发现测量代码的墙钟时间并消除启动/预编译时间是有帮助的。我通过在我想要测量的任何块的最后一行添加say now - ENTER now来实现这一点。 ENTER now由ENTER阶段在块的开头运行。 - donaldh
同样地,为了向其他人展示或在 #raku 上使用 m: 粘贴,可以执行 END say now - INIT now,也就是说,当程序完成时,显示主线开始执行时的时间差。 - Elizabeth Mattijsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接