GAC与JIT的区别

5

所有放置在GAC下的东西都是预编译的(ngened)吗?如果是这样,那么整个.NET都被预编译了,所以CLR无法在运行时进行优化,对吗?

比如,如果你在应用程序中使用List,那么CLR将无法优化List本身,只能优化它在你的应用程序中的使用方式?这不是违背JIT的目的吗,要在运行时获得大量的优化吗?因此,实际上失去了对BCL的所有潜在优化?

4个回答

4

不,GAC并没有自动进行预JIT;然而,GAC是预JIT的前提条件。实际上,只有少数内容可以进行预JIT。此外,如果BCL被预JIT,那么这些优化已经被NGEN完成了,因此“失去所有潜在的优化”不成问题。


谢谢Marc。实际上我不知道prejit是什么。prejit是否等同于ngen?如果是这样,你仍然有运行时优化吗? - Joan Venge
是的,同样的事情。你之所以称它们为“运行时优化”,只是因为通常它们发生在运行时。NGEN的整个目的就是提前完成这些操作,以减少开销。 - Marc Gravell
谢谢Marc。那么可以说,在当前的CLR JIT中,运行时不会得到任何优化,这些优化不能在ngen之前捕获吗? - Joan Venge
Joan,事实并非如此(请参见我回答中的链接文章)。 - ShuggyCoUk
请注意,由于各种类型的代码都会从这种优化中受益,因此微软将来可能会开始实现“热点”式的即时编译。不过我无法预见在4.0中是否会出现这种情况。 - ShuggyCoUk

2
GAC可以包含非ngen的代码(使用ngen时,必须同时包含非ngen的代码和本地映像,因为ngen映像不包含所有所需的元数据)。ngen的代码需要将dll安装到GAC中以实现高效运行(从技术上讲,可以不这样做,但结果是名称验证会触发对你的dll进行完整读取,这可能会使启动时间变得更糟)。
在3.5 SP1之前,ngen编译与运行时编译明显有所不同,请参阅this article了解更多细节。我想这仍然适用于3.5SP1,因为这些问题很难解决。
由于ngen只能给你带来两个重要的优势,你应该考虑是否在你的场景中两者都很重要,以证明使用它们所涉及的复杂性和成本是合理的。
这些dll的启动时间大大缩短了。
要实现真正的优势,所有在启动时加载的dll都需要进行ngened处理,以避免加载jit本身的开销)
原生映像可以在多个进程之间共享内存空间。
如果您只运行一两个进程,则没有什么意义。
我建议阅读这篇文章详细介绍了2.0 ngen中的一些更改,它涵盖了硬绑定等重大改进,并链接到编写高效托管代码的出色通用文档,尽管它已经存在链接腐败,请参阅msdn第5章它所指的文档。 (请注意,该文档已经过时,但许多主题仍然有效)

1

不,全局程序集缓存没有预编译。

框架的新版本确实有一个优化服务在后台运行,进行一些预编译。但由于它在目标系统上运行,所以它所做的所有预编译都是针对该特定系统进行优化的。


-2

如果从GAC加载程序集,则会跳过强名称验证,因为程序集已经通过验证。 GAC的另一个优点是文件保护(仅限管理员)。

NGEN具有自己的本地映像存储。在没有将程序集放入GAC的情况下使用NGEN几乎没有意义。在这种情况下,加载程序集将导致验证其SN签名,这意味着每次加载程序集时都会重新创建加密哈希。

使用ngen的最佳实践也是将程序集放入GAC中。


最佳实践?GAC?对于大多数常见情况,最佳实践是不使用GAC,而只是使用每个项目的文件副本,允许xcopy/robocopy部署。 - Marc Gravell
@Marc:你怎么证明你的观点呢? - Michael Damatov
GAC不是一种部署机制,而是一个版本控制/发现系统。我总是很烦恼必须使用它来进行NGEN。Marc完全正确。 - ShuggyCoUk
抱歉误解了:正如您所读到的,我并没有说您必须使用NGEN,我只是在说如果没有GAC,使用NGEN就没有意义。仅此而已。 - Michael Damatov
使用 ngen 时的最佳实践是将程序集放置在 GAC 中。尽管应用程序应该尽量避免使用 GAC,但共享库或框架更适合使用它,即使如此,它们也应该考虑允许简单的“从私有 bin 路径加载 dll”模型。 - ShuggyCoUk

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