谈谈JIT编译器和本机影像生成器(NGen.exe)
前言
在看《CLR》的时候,作者在开篇的时候提到了NGen.exe,前面一节执行程序集的代码中提到:程序或方法执行前会执行MSCorEE.dll中的JIT函数把要执行方法的IL转换成本地的CPU指令,讲代码放在内存块中,第二次调用方法的时候,由于已对方法进行了验证和编译,所以会直接执行内存块中的代码,不需要再执行JIT函数编译了。因为在方法没调用之前都会要调用JIT函数编译,在这一节的最后作者也提到,通过实验表明,CLR的JIT编译器似乎没有使自己的应用程序达到应有的性能,然后就提到了.Net Framework SDK提供的NGen.exe工具。
疑问
当时看到这段话的时候很兴奋,然后就接着看作者写的NGen.exe的介绍,可惜作者只用了几页的篇幅讲了下,感觉太少了,也有些疑问,然后就在MSDN上搜,找到了《Ngen.exe(本机映像生成器)》,仔细看了下,和作者写的差不多,其中详细写了NGen.exe的用法,自己也照着上面的方法,自己敲了个遍,可能是官方写的太官方或是小弟理解能力有限,总有点云里雾里的,然后又在博客园找到了一位园友写的《本机影像生成器(Ngen.exe)工具使用实践》,仔细看了下,主要是NGen.exe项目的简单应用,不是很全面的介绍NGen.exe的用法。
结合上面所接触的,有几个疑问:
1,JIT编译器的执行条件
上面那位博文的作者在文章中提到
但是《CLR》这本书的作者在写执行程序集中的代码这一节中提到:JIT编译器将本地CPU指令存储到动态内存中。一旦应用程序终止,编译好的代码也会被丢弃。所以再次运行应用程序,JIT编译器必须再次将IL代码编译成本地指令。
就是说程序终止,再次运行程序还是会执行JIT编译器的。但是与上面“实时编译只在程序第一次运行时编译”有点矛盾。
2,NGen.exe的作用
MSDN和《CLR》的作者都说了NGen.exe的作用有两点,改善内存使用情况和更快的应用程序启动速度,这里我只说使应用程序启动速度加快。
NGen.exe操作会把相应的程序集的IL代码编译成本地代码,放到磁盘的某一目录下,下次执行程序的时候CLR会检测是否存在对应程序集由NGen.exe生成的文件,若不存在执行JIT编译器编译,若存在跳过JIT编译器,JIT编译器执行的条件是在执行方法之前编译,这时候我就有点迷糊了,MSDN上写的是NGen.exe的作用是使应用程序启动的速度加快而不是程序运行的速度加快,就是说在程序运行的时候,如果调用某一方法,还是会执行JIT编译器的,就有点矛盾了。或者这样说JIT编译器是不是在程序启动的时候执行,执行所有代码的编译?如果是,那NGen.exe使程序启动的速度加快这个作用是对的,我个人感觉并不是这样,比较那么纳闷的是为什么没有使程序运行的速度加快,因为NGen.exe已经把相关的程序集编译好了,程序调用某一方法的时候就不需要再执行JIT编译器了,少了编译速度不是更快了?
3,NGen.exe安装程序集依赖项
MSDN中提到
但是我试了下并没有安装程序的依赖项
4,NGen.exe检测映像变化
或者不是NGen.exe检测,其他的方式暂时也没发现,如果是自己程序中的程序集发生变化可以通过程序来判断,但是外部的变化就不太好检测了,比如:
5,NGen.exe更新映像
MSDN提供了两种更新映像的方式,但是没有指定程序集更新,如果说程序集发生变化,就需要全部更新映像花费时间太长,下面的更新方式的说明不是很清楚,不知是不是自动检测映像变化更新。
后记
以上疑问,跪求大神指点。。。。
不知是用NGen.exe后会性能会优化多少,暂时没有找到相关的方法测试,有机会会好好测试下,想想NGen.exe的用武之地应该是大型的Winfrom项目,而且业务逻辑应该很复杂的那种,如果只是简单的程序,就没这个必要了。
微信公众号:你好架构
出处:http://www.cnblogs.com/xishuai/
公众号会不定时的分享有关架构的方方面面,包含并不局限于:Microservices(微服务)、Service Mesh(服务网格)、DDD/TDD、Spring Cloud、Dubbo、Service Fabric、Linkerd、Envoy、Istio、Conduit、Kubernetes、Docker、MacOS/Linux、Java、.NET Core/ASP.NET Core、Redis、RabbitMQ、MongoDB、GitLab、CI/CD(持续集成/持续部署)、DevOps等等。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。