【问题标题】:What are the advantages and disadvantages of pre-jitting assemblies in .NET?.NET 中预抖动程序集的优缺点是什么?
【发布时间】:2011-06-17 08:15:20
【问题描述】:

.NET 中预抖动程序集的优缺点是什么?

我听说预抖动会提高性能。什么时候应该 pre-jit,什么时候不应该 pre-jit?

【问题讨论】:

  • 预JITting?这肯定是矛盾的!
  • 我认为 pre-jit 只会提高首次访问性能。编译后,一切都一样了。
  • 第一次访问时 JIT 是的。但是不会立即访问所有代码。 .Net 使用后期绑定在需要时加载所需内容。 + .Net 库本身已经是 NGEN 的。

标签: c# .net jit


【解决方案1】:

“预抖动”或预编译将提高性能,在启动时,因为您会跳过该步骤。每次加载应用程序及其库时 .NET JIT 的原因是,它可以在许多平台和架构上运行,并具有最佳优化,而无需管理您的构建。

因此,您必须权衡在应用启动和库加载时节省几秒钟的时间是否值得让管理员头疼。我认为这样做最常见的用例是服务器安装,您倾向于管理少量机器并且环境非常稳定。例如。您不会为客户端应用程序进行预编译,因为目标环境的可预测性要低得多。

【讨论】:

  • 这并不完全正确。使用 ngen 的“预抖动”发生在消费者的机器上。实际的 .NET 程序集保持不变(因为运行时需要它们,例如反射)。因此,您的编译和部署几乎保持不变 - 您不必针对特定架构。
  • @winSharp93:我添加了一个用例来说明我之前试图提出的观点。
  • 如果平台和操作系统相同,使用 ngen.exe 进行 pre-jit 好不好?示例:如果所有运行 ASP.NET 应用程序的服务器(开发、登台和生产服务器)具有相同的操作系统和硬件
  • 我认为只有当您认为您的应用程序会经常重启或可能频繁加载/卸载库(很少发生)时才真正值得。否则我会避免它,因为它增加了另一个部署问题。请记住,一旦您的应用启动并运行,它如何被 JIT 化并不重要。
  • 我才知道 ASP.NET 不支持 Pre-Jitting,所以它只对通过安装程序安装的应用程序有意义,所以更可能是桌面应用程序support.microsoft.com/kb/331979/en-us
【解决方案2】:

“PRE-JIT”是通过NGen 完成的(从CIL 预编译为本机镜像的过程)。它将编译的 .NET 代码从独立于平台的中间状态转换为特定于平台的阶段。简单来说,它将可以在 Windows、Mac 和 Linux 32 位和 64 位上运行的 .NET 应用程序转换为只能在其中一个上运行的老式 EXE file

.NET 应用程序被编译成一种名为MSIL 的中间二进制格式,它与平台无关。这意味着只要平台支持 .NET,应用程序就可以由任何平台上的任何 CPU 运行。 .NET 在执行期间所做的称为 JIT。每次执行时,JIT 都会在代码实际使用之前编译一次代码。这也意味着只编译使用的代码。

NGen 会给您的应用程序带来性能提升(主要是启动时间),有时非常显着。只要您瞄准正确的平台,对 NGen 来说几乎任何东西都是安全的。例如,如果您的应用程序使用 32 位 DLL 文件,则不应将其 NGen 为 64 位,如果您的 DLL 文件正在被其他应用程序使用,则不应对其进行 NGen。

我建议在安装后运行 NGen,而不是在分发之前运行,这样您就知道该应用程序可以在目标计算机上运行。

【讨论】:

    【解决方案3】:

    您是在谈论 NGen 在执行前生成程序集图像吗? Pre-JIT 在术语上是矛盾的,因为“JIT”意味着及时,就像在执行之前一样。如果您预编译某些东西,根据定义,它不是 JIT-ing。

    优点是,当第一次在代码中加载程序集或类型时,您不会遇到 JITter 可能引入的初始编译延迟。对于非常(可能不明智地)大型程序集/类型,这可能很重要。

    缺点包括无法优化某些只能根据运行时条件确定的内容以及您必须维护图像的事实。此外,所有使用预生成图像的应用程序和程序集(从 .NET 4 开始)都需要完全信任,并且 CAS 会被忽略。

    有关 NGen 的更多信息,请参阅http://msdn.microsoft.com/en-us/library/6t9t5wcf.aspx

    【讨论】:

      【解决方案4】:

      它改善了程序的热启动时间。热启动是程序集数据已经在文件系统缓存中,因此磁盘驱动器不会花费时间来定位磁盘上的 DLL。与冷启动相反,当程序集从未加载过或很久以前加载过时,磁盘驱动器必须首先找到文件。这很慢。您几乎总是只关心冷启动时间,因为这对用户来说非常明显。

      这就是 rub,ngen.exe 会创建一个 extra 文件,该文件需要由磁盘驱动器找到。包含 prejitted 机器代码 (.ni.dll) 的代码。可能会使冷启动变慢。对于“小型”程序集,让 JIT 编译器 jit 代码实际上是有意义的,因为这比磁盘驱动器查找 prejitted DLL 所需的时间要少。究竟什么是“小”,即收支平衡点,很大程度上取决于磁盘驱动器的寻道速度及其碎片状态。您必须进行试验,但请记住,这不会在另一台机器上很好地重复。而且像这样的实验本身就很困难,你很容易得到一个温暖的开始。

      【讨论】:

        【解决方案5】:

        我已经看到了执行确定性很重要的优势。通常,您需要避免像瘟疫一样对时间敏感的执行。有时这是不可避免的。一种情况是与外部硬件交互时,某些行为是异步的,尤其是当有很多步骤是串行执行而不是重复执行时。这意味着每个步骤都必须是 jitted 并且硬件同时在做自己的事情(异步通信)

        我们总是在安装过程中生成我们的库。我们的库可以访问不同的硬件设备,其中许多设备最初并不是为自动化而设计的。

        【讨论】:

          【解决方案6】:

          当您说“pre-jitting”时,您可能是指使用NGen (ngen.exe) 来预编译您的程序集(?)。

          使用 NGen 并没有真正的缺点(除了一些额外的磁盘使用字节数)。但是,为了使用它,您要预编译的程序集必须位于 GAC(全局程序集缓存)中。但是,您需要管理员权限才能将它们带到那里。
          因此,它不适合您希望通过复制和粘贴非常轻松地部署的应用程序。

          是的,使用 NGen 可能会提高应用程序的性能(即使在运行时,因为在 JIT 编译期间跳过了一些优化以节省编译时间)。因此,请尽可能使用 NGen,尤其是对于长时间运行的应用程序和您实际上想要在本地安装的应用程序。

          【讨论】:

          • 我不确定我会说它有 no 缺点。它在某些情况下会有所帮助,但这是一个维护考虑,不提供与 JIT 的 1:1 奇偶校验(例如,没有部分信任)
          猜你喜欢
          • 2010-11-09
          • 1970-01-01
          • 2014-01-24
          • 2012-12-21
          • 1970-01-01
          • 2011-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多