.NET程序首先被编译成MSIL代码。当它被执行时,JIT编译器会将它编译成本机代码。
我想知道:
这些JIT编译的机器码存储在哪里?它是否只存储在进程的地址空间中?但由于第二次启动程序的速度比第一次快得多,我认为即使在执行完成后,这些本机代码也一定存储在磁盘上的某个地方。但是在哪里呢?
发布于 2010-07-21 09:47:09
记忆。它可以被缓存,这是ngen.exe的工作。它生成程序集的.ni.dll版本,其中包含机器码并存储在GAC中。之后自动加载,绕过JIT步骤。
但这与为什么你的程序第二次启动得更快没有什么关系。第一次你有一个所谓的“冷启动”。这完全取决于在硬盘驱动器上查找DLL所花费的时间。第二次热启动时,DLL已经在文件系统缓存中可用。
磁盘速度很慢。SSD是一个显而易见的解决方案。
Fwiw:这不是托管代码独有的问题。具有大量DLL的大型非托管程序也有此功能。在大多数开发机器上出现的两个典型示例是Microsoft Office和Acrobat Reader。他们作弊。安装后,它们会在Run注册表项或Startup文件夹中放置一个“优化器”。这些优化器所做的全部工作就是加载主程序使用的所有All,然后退出。这启动了文件系统缓存,当用户随后使用该程序时,它将快速启动,因为它的热启动速度很快。
就我个人而言,我觉得这非常恼人。因为他们真正做的是减慢我登录后可能想要启动的任何其他程序的速度。很少是Office或Acrobat。我特意删除了这些优化器,如果必要的话,当一个糟糕的更新把它放回原处时,我会重复删除它们。
你也可以使用这个技巧,但请负责任地使用它。
发布于 2010-07-21 09:36:38
正如其他人指出的那样,在你的例子中,代码是基于每个进程进行JIT的,而不是缓存-你在第二次加载时看到的加速是程序集的操作系统磁盘缓存(即在内存中)。
然而,虽然在该框架的桌面/服务器版本中没有缓存(除了操作系统磁盘缓存之外),但是在该框架的另一个版本中存在JIT机器代码的缓存。
有趣的是.Net Compact Framework ( Windows phone7版本的phone7)中发生了什么。最近的进展看到一些JIT框架代码在进程之间共享,其中JIT代码确实被缓存。这主要是为了在受限设备(如移动电话)中获得更好的性能(加载时间和内存使用)。
因此,对于这个问题,在CLR的桌面\服务器版本中没有直接的框架缓存JIT代码,但在最新版本的紧凑框架中将会有,即NETCF。
参考:我们相信共享
http://blogs.msdn.com/b/abhinaba/archive/2010/04/28/we-believe-in-sharing.aspx
发布于 2010-07-21 09:27:53
每次第一次执行一个方法时,JIT编译的机器码都缓存在每个方法的内存中。我不认为它会被缓存到磁盘上。
你可能会发现第二次加载进程的速度更快,因为Windows在第一次运行时(在内存中)缓存了进程使用的文件(dll、资源等)。在第二次运行时,不需要转到磁盘,在第一次运行时可能已经这样做了。
您可以通过running NGen.exe确认这一点,以实际预编译适用于您的体系结构的机器码,并比较第一次和第二次运行的性能。我敢打赌,由于操作系统中的缓存,第二次运行仍然会更快。
https://stackoverflow.com/questions/3295622
复制相似问题