使.NET可执行文件在第一次加载时更快

5
我用C#创建了一个简单的Windows Forms可执行文件(所谓简单,是指它只有大约20种方法,但只有一个窗口),目标为.NET Framework 2.0。当应用程序加载时,在构造函数中除默认的InitializeComponent();外不做其他操作。
第一次打开应用程序时,在我的Windows 8上需要大约7秒才能加载。然后在接下来的打开中只需要不到一秒钟。
在我尝试的Windows XP中,第一次加载需要大约30秒。我的一些朋友在测试该应用程序时也抱怨第一次加载需要很长时间(大约30秒)。然后加载速度更快(1或2秒)。
我认为这可能是因为.NET Framework尚未加载,因此需要一些时间在他们的计算机上加载。 您是否遇到过.NET应用程序的同样问题?
你有什么线索为什么会发生这种情况,我该如何解决?
编辑-我看到有些人建议使用NGEN。然而,如果这需要在每台将使用应用程序的计算机上执行,则无法解决此问题。我想向广大“普通用户”发布我的应用程序,如果要求他们执行额外的操作才能使用我的应用程序,那就没有意义了。我们已经需要.NET Framework,这已经够糟糕的了。我的应用程序应该是一个独立的EXE,没有任何依赖关系(除了框架)。
谢谢。

可能用户的内存已经耗尽,因此必须在应用程序加载之前将内容移动到虚拟内存中。在这种情况下,NGEN帮助不大。 - leppie
3个回答

6

您可以尝试使用 NGEN 预生成本地映像,它会在应用程序加载时由 .NET 使用。

您可以在此处找到更多信息 - http://msdn.microsoft.com/en-GB/library/6t9t5wcf(v=vs.80).aspx

这些通常是平台相关的,不能转移,因此您需要在每台部署的计算机上执行此操作。


谢谢你的帮助。然而,这似乎不是我问题的好解决方案。请查看我问题中的编辑。干杯。 - Nuno
1
关于您的编辑,如果您创建了一个合适的安装程序,您的用户就不需要做任何事情,他们只需点击即可,您可以指示它为您运行NGEN。 - Lloyd
1
Lloyd是正确的:你可以在安装时对.NET程序集进行NGEN。你可以使用WiX工具包(www.wixtoolset.org)来完成,可能还有许多其他的安装程序构建工具也可以实现。 - Jeffrey Sax
好的,就像我在编辑中所说的那样,我想要一个“独立的EXE”文件。为什么他们需要安装一个只是简单单窗口工具的应用程序呢? :/ - Nuno
@NunoPeralta 因为你有其他的任务要执行吗?听起来你很固执 :P 你可以让你的程序在应用程序上运行 NGEN,虽然第一次仍然会受到性能影响。 - Lloyd

5
这很可能是由于CIL的即时编译引起的。您可以使用NGen为您正在运行的环境编译代码。但是,如果您选择这条路,您很可能会失去.Net的平台无关性。
MSDN上的这篇博客文章详细解释了NGen的性能优势,建议您阅读一下。 评论后更新 正如Lloyd在他的回答中指出的那样,如果您给用户一个安装程序,可以在此时针对应用程序正在安装的环境运行NGen。
但是,如果NGen不是一个选项,那么我建议您使用附加了分析器的应用程序启动。它可以突出显示代码中的任何性能瓶颈。如果您有任何单例或昂贵的静态初始化程序,它们将被标记为这样,并为您提供重构的机会。

有许多优秀的 .Net 性能分析工具(详见此 SO 问题),个人推荐看看 dotTrace - 它们还提供一个为期一个月的免费试用期,这可能已经足够你的应用程序了。


附注:我认为这与JIT无关,因为它是每个实例的。看起来像是加载/缓存所有DLL和其他磁盘资源。 - Alexei Levenkov
谢谢你的帮助。然而,这似乎不是我问题的好解决方案。请参见我问题中的编辑。干杯。 - Nuno
好的,正如我在编辑中所说,我想要一个“独立的EXE”文件。为什么他们需要安装一个简单的单窗口工具应用程序呢?:/ 是的,我知道dotTrace。我可能会尝试一下它来优化我的应用程序。谢谢你的提示。很遗憾没有其他解决方案。我对C#感到非常失望,如果你想商业化你的应用程序,就会遇到太多问题。是时候开始使用C语言了... - Nuno
您可以使用 NGen 提供独立的 exe,但是您需要为每个最终用户所在的环境创建不同的可执行文件。 - Rich O'Kelly

0
[...] 目标是.NET Framework 2.0。当应用程序加载时,在构造函数中除了默认的InitializeComponent();之外,它什么都不做。
实际上这并不是完全正确的。应用程序还会加载类型,初始化静态构造函数等。
在大多数情况下,当我遇到性能问题时,我通常使用分析器…… 这里可能发生很多事情,分析器是获取一些洞察力的最简单的方法之一。有一些不同的选项可供选择;就我个人而言,我喜欢Red-Gate的分析器,他们有一个可以使用的试用版。
值得注意的是,这种情况发生的方式已经在.NET Framework中发生了变化。如果您在2.0中无法获得所需的性能,则可以尝试其他框架。当然,Windows XP可能是一个小问题...

谢谢您的回复。我在引用的句子中所指的是,在应用程序开始时我不进行任何“自定义”处理。我知道所有静态内容也必须被加载。顺便说一下,它们只有很少。为什么Windows XP是一个小问题呢?因为仍有许多用户在使用它,我被“迫”使用.NET FW 2.0。不幸的是,FW 4.5与XP不兼容。 - Nuno
1
我的意思是,.NET 4.0将初始化更改为“惰性”,而.NET 2.0具有“急切”的初始化。简单来说,在.NET 2.0中,在应用程序启动之前,所有类型(和静态)都会被初始化,而在.NET 4.0中则不会。只需加载并初始化一个空的winforms应用程序就应该非常快。 - atlaste

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接