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

时间:2009-04-15 11:06:51

标签: c# .net optimization compiler-construction jit

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

在我的家用机器上,回放循环的第一次运行占用了可用时间的大约50%-60%,(我认为这是由于JIT正在完成其工作),然后对于后续循环,它会下降到稳定的5%消费。问题是,如果我在较慢的计算机上运行应用程序,第一次运行占用的时间超过可用时间,导致播放中断并弄乱输出音频,这是不可接受的。之后,它降至8%-10%的消费量。

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

所以,我对JIT有严重的问题。虽然应用程序即使在非常慢的机器中也能很好地运行,但这些“编译风暴”将成为一个大问题。我正在试图弄清楚如何解决这个问题,我想出了一个想法,即用一个属性来标记所有“明智的”例程,该属性将告诉应用程序在启动时预先“挤压”它们因此,当他们真正需要时,他们将完全优化。但这只是一个想法(我也不太喜欢),我想知道是否有更好的解决方案来处理整个问题。

我想听听你们的想法。

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

编辑:

内存消耗和垃圾收集没有问题,我正在使用对象池,播放期间的最大内存峰值为304 Kb。

4 个答案:

答案 0 :(得分:16)

您可以使用PrepareMethod ...方法触发JIT编译器在应用程序初始化例程期间编译整个程序集集(无需使用NGen)。

此解决方案在此处有更详细的描述:Forcing JIT Compilation During Runtime

答案 1 :(得分:4)

初始速度确实听起来像Fusion + JIT,ILMerge(适用于Fusion)和NGEN(适用于JIT)可以提供帮助;您可以在启动时始终通过系统播放静音轨道,以便在没有用户注意到任何失真的情况下完成所有艰苦工作?

NGEN是一个不错的选择;是否有原因你不能使用它?

在初始加载之后提及的问题听起来像是与JIT相关。也许垃圾收集。

您是否尝试过分析? CPU和内存(集合)?

答案 2 :(得分:3)

正如Marc所说,持续的峰值听起来不像JIT问题。其他要寻找的东西:

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

  • 非规格化。在处理可能导致CPU峰值的非常小的浮点数时,某些类型的处理器存在问题。有关详细信息,请参阅http://www.musicdsp.org/files/denormal.pdf

编辑:

即使你不想使用NGen,至少要比较一个NGen版本,这样你才能看出JITing有什么区别

答案 3 :(得分:2)

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