C# 预加载所有部件(JIT)

C# 预加载所有部件(JIT),c#,performance,assemblies,jit,.net-assembly,C#,Performance,Assemblies,Jit,.net Assembly,我们在第一次加载一些重UI屏幕时就遇到了麻烦。我们的项目分为一个主要的可执行文件和几个DLL文件。DLL文件还可以包含UI屏幕,这些屏幕在第一次加载时会变慢 是否有一种方法(在代码中)可以预加载所有引用的程序集以避免JIT编译命中 我知道有一种工具叫做。是否可以在开发环境中运行NGen,以便我们可以立即看到其效果?理想情况下,我们希望从代码中预加载引用的程序集 将C#.NET 3.5与DevExpress一起用于我们的UI组件。您只需创建位于外部程序集中的类的实例即可。只需在有限的范围内调用构造

我们在第一次加载一些重UI屏幕时就遇到了麻烦。我们的项目分为一个主要的可执行文件和几个DLL文件。DLL文件还可以包含UI屏幕,这些屏幕在第一次加载时会变慢

是否有一种方法(在代码中)可以预加载所有引用的程序集以避免JIT编译命中

我知道有一种工具叫做。是否可以在开发环境中运行NGen,以便我们可以立即看到其效果?理想情况下,我们希望从代码中预加载引用的程序集


将C#.NET 3.5与DevExpress一起用于我们的UI组件。

您只需创建位于外部程序集中的类的实例即可。只需在有限的范围内调用构造函数(我的意思是在函数中声明变量。它不应该是全局变量,因为它会延迟GC处理该实例)。这将加载程序集,编译并缓存它。您甚至可以在后台线程中执行此操作,这样主线程将保持响应能力。

看看。另一个选项是将所有程序集合并为一个程序集。每当我使用ILMerge时,我都会向其中添加一个生成后命令,以便它自动发生。另一种选择(未经测试)是,如果您不介意较长的启动时间,您可以在每个程序集开始时手动调用Assembly.Load()。

您可以在任何机器上使用NGen-CLR中没有“开发环境”的概念。。。使用时,请确保实际使用了NGen图像(有关说明,请参阅,并在文档中查找FusLogVw注释)

您还可以通过调用所有您希望运行的代码(如Davita所建议的)来预JIT,但是您需要调用所有类的每一个方法,这些方法并不完全实用

您应该分析应用程序以查看实际花费的时间-它可能是从磁盘读取程序集,而不是JIT本身。。。您可以通过启动应用程序、查看表单、关闭应用程序并重复步骤大致了解它。如果第二次运行速度快得多,那么应用程序大部分时间都在从磁盘读取数据,而不是进行JIT。

您是否尝试过/查看过

也就是说,对要预JIT的每个部件执行以下操作

static void PreJIT()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
}

我个人发现,在“程序”中加入预抖动在某些应用程序中有所帮助,但这是一个特定情况的问题

更重要的是,中的代码在遇到抽象方法时会崩溃,因此添加了两行代码以跳过抽象方法

static Program()
{
    foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
    {
        foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly |
                            BindingFlags.NonPublic |
                            BindingFlags.Public | BindingFlags.Instance |
                            BindingFlags.Static))
        {
            if ((method.Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract|| method.ContainsGenericParameters)
            {
                continue;
            }
            System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(method.MethodHandle);
        }
    }
    Console.WriteLine("jitted!");
}

我认为这可以概括为:如何使引用多个程序集的程序更快地加载。我们已经研究了ILMerge,当我们发布到生产环境中时,将把所有程序集合并到一个更大的可执行文件中。我想真正的问题是,我们能在开发环境中看到NGEN的好处吗?加载程序集不会JIT大多数方法(如果有的话)。它将强制磁盘访问时间/程序集加载本身提前进行。使用
assembly.Load()
不会有任何帮助。看看。这不会JIT大部分代码(只会显式调用)。Alexei,谢谢你的评论。如果我们在每次“第一次”加载表单时关闭应用程序,那么速度会很慢。加载表单的每个后续调用都发生得非常快。每次编译应用程序并运行它时,结果都是一样的。JIT-NGEN很可能会有所帮助。我的测试表明,就JIT和优化而言,
PrepareMethod
与调用方法不同。