我们正在第一次加载一些重型UI屏幕。我们的项目分为一个主要的可执行文件和几个DLL文件。 DLL文件还可以包含UI屏幕,这些屏幕在第一次加载时速度很慢。
有没有办法(在代码中)我们可以预加载所有引用的程序集,以避免JIT编译命中?
我知道有一个名为NGen的工具。是否可以在开发环境中运行NGen,以便我们可以立即看到它的影响?理想情况下,我们希望从代码中预加载引用的程序集。
将C#.NET 3.5与DevExpress一起用于我们的UI组件。
答案 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。