支持 JIT 的分析器

目标:拥有一个了解 PyPy JIT 的分析器,并显示在哪些循环中花费了多少时间。

长期目标:将分析器收集的数据与 jitviewer 集成。

想法是在每次进入和退出循环或桥接时在 PYPYLOG 中记录一个事件。

预期输出

[100] {jit-profile-enter loop1 # 例如一个入口桥接 [101] jit-profile-enter} … [200] {jit-profile-enter loop0 # 从 loop1 跳转到 loop0 [201] jit-profile-enter} … [500] {jit-profile-exit loop0 # 例如由于保护失败 [501] jit-profile-exit}

在这个例子中,从 loop1 退出是隐式的,因为我们正在进入 loop0。因此,我们在入口桥接中花费了 200-100=100 个刻度,在实际循环中花费了 500-200=300 个刻度。

如何处理“内部”桥接?

“内部桥接”是指那些跳转回其源循环的桥接。有两种处理它们的方法:

  1. 我们忽略它们:我们记录何时进入循环,但不记录何时跳转到已编译的内部桥接。退出事件仅在非编译保护失败或跳转到另一个循环的情况下记录。
  2. 我们记录每个内部桥接的进入/退出。

解决方案 (2) 的缺点是,某些循环在每次迭代时都会使用桥接。因此,在这种情况下,我们将记录大量事件,可能会增加大量开销,从而使分析数据变得毫无用处。

检测进入/退出循环

进入方式

  • 在跟踪/编译之后
  • 从解释器,如果循环已经编译
  • 从另一个循环,通过 JUMP 操作
  • 从热保护失败(如果我们选择上面的解决方案 (1),我们将忽略它)
  • XXX:我是否遗漏了什么?

退出方式

  • 保护失败(进入黑洞)
  • 保护失败(跳转到桥接)(如果选择解决方案 (1),则忽略)
  • 跳转到另一个循环
  • XXX:我是否遗漏了什么?

关于 call_assembler:我认为一开始,我们应该忽略 call_assembler:在调用内部花费的时间将计入调用它的循环。