【问题标题】:Measure startup performance c# application测量启动性能 c# 应用程序
【发布时间】:2019-04-03 22:04:47
【问题描述】:

我注意到有时 .net 4.0 c# 应用程序需要很长时间才能启动,而没有任何明显的原因。我能否确定实际发生了什么,加载了哪些模块?我正在使用许多外部程序集。将它们加入 GAC 可以提高性能吗?

.NET 4 是否比 .NET 2 慢?

【问题讨论】:

  • 在调试器下运行,Activator.CreateInstance 在 .NET 4 上非常慢。

标签: c# performance


【解决方案1】:

.NET 程序有两种不同的启动行为。它们被称为冷启动和热启动。冷启动是缓慢的,当您之前没有启动 .NET 程序时会得到它。或者当您启动的程序很大并且以前从未运行过时。操作系统必须在磁盘上查找程序集文件,它们在文件系统缓存 (RAM) 中不可用。这需要一段时间,硬盘很慢并且有很多文件要查找。一个小型的无用 Winforms 应用程序必须加载 51 个 DLL 才能启动。一个无操作的 WPF 应用程序有 77 个 DLL。

在不久前加载程序集文件时,您会得到一个热启动。程序集文件数据现在来自 RAM 而不是慢速磁盘,即 zippedy-doodah。现在唯一的启动开销是抖动。

对于冷启动,您几乎无能为力,程序集必须以某种方式从磁盘中取出。快速磁盘有很大的不同,SSD 尤其有效。使用 ngen.exe 对程序集进行 pre-jit 实际上会使问题变得更糟,它会创建另一个需要查找和加载的文件。这就是 Microsoft 建议 对小型程序集进行 prejitting 的原因。看到 .NET 4 程序的这个问题也很明显,你没有很多程序绑定到版本 4 CLR 和框架程序集。无论如何还没有,这会随着时间的推移自行解决。

此问题还有另一种自动消失的方法。 Windows SuperFetch 功能将开始注意到您经常加载 CLR 和 jitted 框架程序集,并将开始自动将它们预加载到 RAM 中。与 Microsoft Office 和 Adob​​e Reader 的“优化器”使用的技巧相同。它们也是具有大量 DLL 依赖项的程序。非托管的,问题不是特定于.NET。这些优化器很粗糙,它们会在您登录时预加载 DLL。这是解决问题的“我真的很重要,搞砸一切”的方法,确保禁用它们,这样它们就不会占用 SuperFetch 可以使用的 RAM 空间。

【讨论】:

  • 我如何跟踪正在发生的事情?我注意到主窗体的构造函数需要很长时间才能执行(尤其是 InitializeComponents),但并非每次启动应用程序时都会发生这种情况,而且通常在启动时需要更多时间。
【解决方案2】:

启动时间很可能是由于运行时 JIT 将程序集 IL 编译成机器代码执行。它也可能受到调试器的影响 - 正如另一个回答者所建议的那样。

除此之外 - 我将讨论在用户机器上“在野外”运行的应用程序,没有调试器等。

.Net 4 中的 JIT 编译器,我认为可以公平地说,比 .Net 2 中的更好——所以不;它并不慢。

您可以通过在应用程序的程序集上运行ngen 来显着缩短启动时间 - 这会将 EXE 和 DLL 预编译为本机映像。但是,这样做会失去一些灵活性,而且通常没有多大意义。

您应该会看到一些用 C++ 编写的 MFC 应用程序的启动时间 - 都是本机代码,但根据它们的链接方式,它们可能需要同样长的时间。

当然,这也取决于应用程序在启动时实际执行的操作!

【讨论】:

    【解决方案3】:

    我认为将您的程序集放入 GAC 不会提高性能。 如果可能的话,记录您在 Loading 或 Intialize 事件中编写的每条指令,这可以帮助您确定哪个语句实际上需要时间,这样您就可以确定加载时间的库。

    【讨论】:

    • 我读到在 GAC 中安装程序集(我对从 Devexpress 使用的 UI 程序集有很多依赖项)将减少启动时间,因为所有程序集的签名都需要已验证。对吗?
    • @Andera 你在一定程度上是对的,但它不会给你正在寻找的性能带来相当大的提升。我认为它会使性能提高 15-20%。您在项目中使用企业库吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-02
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多