3

.NET 语言都编译为中间语言 ( MSIL )。

据我所知,在执行期间(有时在其他阶段,我并不完全了解 - NGEN),代码正在被 JITted(从MSIL编译成实际的机器代码)。

我想知道在 JITting 代码之后是否存在来自代码在 CLR 上执行的事实的性能“惩罚”,或者代码的行为是否与任何其他本机代码“相同”?

4

3 回答 3

5

有许多性能差异:

  1. 托管对象的空闲存储实现为堆栈,而不是堆(大对象堆除外),并且开销低于大多数本机分配器使用的堆。但是您稍后会为垃圾收集和压缩付费。

  2. JIT 可以内联一些 AOT 编译器必须保留为虚拟的调用(即调用其他程序集)。但是 AOT 编译器可以花更多时间寻找优化机会。

  3. 理论上,JIT 可以使用运行代码的特定 CPU(例如 AVX)上的高级指令。不过,仍在等待真正充分利用它们的 JIT。

  4. AOT 编译器可以使用分析数据来控制代码内存的布局。JIT 编译器几乎总是按照编译的顺序将函数发送到内存中。

于 2012-07-30T21:08:56.390 回答
1

JITed 代码的主要性能损失是首次运行时编译代码所花费的时间。这通常只会显示为(稍微,也许是难以察觉的)更长的启动时间,但如果您在 CGI 之类的场景中使用它,它会产生真正的影响,其中会产生一个新进程来处理每个请求。并不是说用 .NET 编写的 CGI 脚本是一个常见的用例,但这是第一个出现在我脑海中的示例,所以我将使用它来运行。

NGen 可以通过跳过 JIT 步骤来缩短您的启动时间。在频繁运行的短期运行程序(如 CGI 脚本)中,好处将是最大的。(或者也许一个设置为自动启动的 Windows 服务是一个更好的例子,现在我想到了。)对于不经常运行的程序,可执行文件不太可能缓存在内存中,因此可能必须从每次磁盘。从磁盘读取所需的时间很可能会支配启动时间并压倒 NGen 的优势。对于长时间运行的程序,启动时间可能不是一个重要的性能特征。

于 2012-07-30T21:36:09.093 回答
0

通常,本机编写的代码性能更高,因为您可以使用在设计时可能需要了解的特定架构可用的优化,例如 SSE。对于一种或另一种语言的性能,还需要考虑其他事项,例如垃圾收集与手动内存管理。

就 NGEN 而言,我认为 JITTED 代码和 NGEN 所做的工作之间不会有太大的性能差异,除了 JITTED 代码是在运行时生成的(当实际编译发生时会导致性能损失)。

于 2012-07-30T21:05:01.057 回答