预加载所有组件(JIT)

时间:2011-03-03 01:50:30

标签: c# performance assemblies jit .net-assembly

我们正在第一次加载一些重型UI屏幕。我们的项目分为一个主要的可执行文件和几个DLL文件。 DLL文件还可以包含UI屏幕,这些屏幕在第一次加载时速度很慢。

有没有办法(在代码中)我们可以预加载所有引用的程序集,以避免JIT编译命中?

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

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

5 个答案:

答案 0 :(得分:7)

您是否尝试过/ this

也就是说,对于要预先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);
        }
    }
}

答案 1 :(得分:7)

我个人发现将预先抖动放在“程序”中对某个应用程序有帮助,但这是一个特定情况的问题。

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

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!");
}

答案 2 :(得分:6)

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

你可以在任何机器上使用NGen - 在CLR中没有“开发环境”的概念......当你使用它时,确保实际使用了NGen的图像(参见 Native Image Generator (Ngen.exe) < / em>获取说明并在文档中查找FusLogVw注释。

你也可以通过调用你期望运行的所有代码来预先JIT(如Davita建议的那样),但你需要调用所有类的每个方法,这些方法并不完全实用。

您应该分析您的应用程序以查看实际花费的时间 - 它可能是从磁盘读取程序集,而不是JITing本身......您可以通过启动应用程序,查看表单,关闭应用和重复步骤。如果第二次运行要快得多,那么应用程序大部分时间都会从磁盘读取,而不是JITing。