代码之家  ›  专栏  ›  技术社区  ›  Trap

强制.NET JIT编译器在应用程序启动期间生成最优化的代码

  •  12
  • Trap  · 技术社区  · 16 年前

    我正在用C(基本上是一个多轨编辑器)编写一个DSP应用程序。我已经在不同的机器上对它进行了很长一段时间的分析,我注意到了一些“奇怪”的事情。

    在我的家用机器上,第一次运行回放循环大约占可用时间的50%-60%(我假设这是由于JIT的工作),然后对于随后的循环,它将下降到稳定的5%消耗。问题是,如果我在速度较慢的计算机上运行应用程序,第一次运行会占用比可用时间更长的时间,从而导致播放中断并干扰输出音频,这是不可接受的。之后,它会下降到8%-10%的消费量。

    即使在第一次运行之后,应用程序也会不时地调用一些耗时的例程(大约每2秒一次),这会导致稳定的5%的消耗经历20%-25%的极短峰值。我注意到,如果让应用程序运行一段时间,这些峰值也会下降到7%-10%。(我不确定是否是因为JIT重新编译了这些代码部分)。

    所以,我对JIT有一个严重的问题。尽管应用程序即使在速度非常慢的机器上也能很好地运行,但这些“编译风暴”将是一个大问题。我正在尝试解决这个问题,我想出了一个主意,就是用一个属性标记所有“合理”的例程,该属性将告诉应用程序在启动期间预先“挤压”它们,以便在真正需要它们时对它们进行完全优化。但这只是一个想法(我也不太喜欢),我想知道是否有更好的解决整个问题的方法。

    我想听听你们的想法。

    (ngen应用程序不是一个选项,我喜欢并希望获得所有JIT优化。)

    编辑:

    内存消耗和垃圾收集程序不是问题,我正在使用对象池,播放期间的最大内存峰值是304 KB。

    4 回复  |  直到 9 年前
        1
  •  16
  •   Liran    9 年前

    在应用程序的初始化例程期间,可以使用 PrepareMethod …方法(不必使用 NGen )

    下面将更详细地描述此解决方案: Forcing JIT Compilation During Runtime .

        2
  •  4
  •   Marc Gravell    16 年前

    初始速度听起来确实像fusion+jit,这将有助于ilmerge(用于fusion)和ngen(用于jit);您总是可以在启动时在系统中播放一个静默的轨迹,这样所有的努力工作都不会让用户注意到任何失真?

    恩根是个不错的选择;有没有 原因 你不能用它吗?

    你提到的问题 之后 初始载荷do 听起来像是和JIT有关。也许是垃圾收集。

    你试过分析吗?CPU和内存(集合)?

        3
  •  3
  •   Jim Arnold    16 年前

    正如马克提到的,持续的峰值听起来不像是JIT问题。其他需要注意的事项:

    • 垃圾收集-您在音频处理期间分配内存吗?如果您正在创建大量的垃圾,甚至是保存在Gen0集合中的对象,这可能会导致明显的峰值。听起来您正在进行某种预分配,但要注意库代码中隐藏的分配(甚至foreach循环也可以分配!)

    • Denormals。在处理可能导致CPU峰值的非常小的浮点数时,某些类型的处理器存在问题。见 http://www.musicdsp.org/files/denormal.pdf 详情。

    编辑:

    即使你不想使用ngen,至少要比较一个ngen的版本,这样你就能知道抖动有什么不同。

        4
  •  2
  •   dthorpe    14 年前

    如果您认为自己受到了JIT的影响,那么可以使用NGEN预编译应用程序,然后再次运行测试。ngen编译的代码中没有JIT开销。如果你仍然在ngen'd应用程序中看到峰值,那么你知道它们不是由JIT引起的。