. net在第一次运行方法时发布代码非常慢.如何解决它没有NGen

本文关键字:何解决 解决 NGen 非常 代码 运行 第一次 方法 布代码 net | 更新日期: 2023-09-27 18:17:54

我已经在发布模式(x64)下部署了一个应用程序,我希望它很快,但是我注意到每当第一次执行一个新方法或一组方法时,就会出现严重的减速。我说的严重是指第一次执行100-200毫秒,之后的执行时间不到1毫秒。

从我发现的,这似乎是由于JIT编译器应该编译方法第一次运行。我预计会有一些延迟,但在执行过程中,100毫秒的延迟是灾难性的。

我知道NGen,但是NGen需要在机器上安装时完成。这些机器都有有限的用户权限,不能安装任何东西。应用程序作为可执行文件和参考dll进行部署。我想这就是为什么我永远无法让NGen工作的原因。

是否有任何方法使JIT在启动时编译每个方法?

我想创建虚拟变量并添加一个启动例程,除了运行每个方法一次之外什么都不做,所以它可以在启动完成时是什么。这是否足以强制编译,或者是否需要单独执行方法的每个代码路径?

. net在第一次运行方法时发布代码非常慢.如何解决它没有NGen

哇。这样的延迟对JIT来说是不寻常的。配置你的应用到,确保瓶颈是JIT。

现在,如果它真的是JIT,这里有一个比到处添加虚拟参数更好的方法:

对每个非泛型方法使用RuntimeHelpers.PrepareMethod。这个函数将强制JIT处理它。

您还可以在每个类上使用RunClassConstructor方法来…那么,运行它们的静态构造函数。

下面是一些(完全未经测试的)代码:

foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
    if (type.IsGenericTypeDefinition || type.IsInterface)
        continue;
    RuntimeHelpers.RunClassConstructor(type.TypeHandle);
    foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly))
        RuntimeHelpers.PrepareMethod(method.MethodHandle);
}

NGen应该在每台机器上安装时运行。让它成为安装过程的一部分。这将为相关的架构编译。

如果您的延迟确实是由于jit,这应该解决它。

我的第一个解决方案是手动创建类的虚拟实例,然后使用可选的虚拟bool变量调用方法,该变量默认为false。这是可行的,但需要在每个粗糙且耗时的方法中添加这个虚拟对象。

Lucas Trzesniewski的答案更深入,因为它准备了代码中的所有类和所有方法,并且不需要对我的任何代码进行任何更改,因此更容易实现。唯一的代价是,由于太过彻底,它需要更长的时间来完成,大约需要0.5到1.5秒,或者可能比我选择性启动的时间长0.5到1秒。在我的情况下,这是值得的,以确保代码中不会发生延迟。

除了初始启动之外,内存或CPU使用没有明显的峰值,内存使用实际上略有下降,可能是因为所有代码现在都被编译和优化了。