Ngen生成Native代码实战及优缺点分析

 

      先科普一下,.Net是一个用于Windows的托管代码模型,用于高效构建具备视觉上引人注目的用户体验的应用程序。但这个模型生成的代码并不是可执行代码,而是由.Net公共语言运行库环境执行的IL代码。因此,每次执行代码时,都会由.Net将IL代码翻译为机器代码。因此,效率上天然会受到必定影响。对此,微软在.Net中附带一个将IL代码转换为Native代码的工具Ngen.exe。它能够建立一份程序集文件至相似于C:\WINDOWS\assembly\NativeImages_v4.0.30319_32的文件夹内。这个文件夹下一般会包含以下信息:dom

            1.公共语言运行库的版本函数

            2.x64版本或x86版本信息(包括x86,x64和Itaninum)工具

            3.Native代码性能

      若是这样一个Ngen程序集被建立了(暂且这么叫它),那么,CLR载入程序集文件时,就不会实时编译,而会使用Ngen程序集中的代码,因而,应用程序集的启动速度、运行速度都获得了提高。优化

      看起来很美好,是吧(哪一种技术听起来不美好…)?既获得了托管代码的全部优势,还获得了近似于普通非托管代码的执行性能咱们先来分析一下它的优缺点:ui

Advantage:1.提升启动速度, 由于代码已经编译成Native代码, 因此在运行时就不须要编译了。翻译

                2.减小应用程序的工做集,若是一个程序集会被同时载入到多个进程/Appdomain,,在这个程序集上运行Ngen能减小应用程序的工做集。由于Ngen会将IL编译为Native代码后,保存到单独的文件夹。这个文件夹能在同一时刻对多个进程空间起做用,且容许代码共享。因此, 每一个进程/AppDomain没必要为本身拷贝一份代码。debug

Disadvantage:1.编译Native代码后,原IL代码不可删除。由于运行的时候,CLR须要访问程序集的metadata,这须要IL与Native二者。且不少人认为发布Native代码就能够避免IL原始代码泄露,以保护知识产权,其实这是错的。orm

                     2.NGen文件可能会过期: 当CLR载入NGen所映射文件时,,它会比较之前编译的代码和当前的执行环境的不少特征, 若是任何特征不匹配,预编译的文件就不能被使用, JIT编译器进程就要使用。下面必须被匹配的部分特征列表:进程

                     ① 程序集模块的版本ID (MVID)

                     ② 被引用的程序集的版本ID

                     ③ 处理器类型

                     ④ CLR版本

                     ⑤ Build类型(release, debug, optimized debug, profiling, 等等)

                     若预编译程序集过期,能够以升级的方式运行Ngen.exe来补救, 这告诉工具对之前曾经被执行Ngen操做的全部的程序集上运行Ngen。当终端用户安装.NET Framework的一个新service pack,,那么service pack的安装程序将会在更新模式下自动运行Ngen.exe, 使得NGen文件保持和CLR的版本一致。

                     4. 较差的载入时性能(重定位/绑定): 程序集文件还是标准的Windows PE文件, 每一个文件包含着一个优先使用的基地址。 CLR会对于内存地址进行计算,致使额外的性能消耗。然而, Ngen程序集文件的一些内存地址引用是静态计算的, 当Windows加载一个Ngen文件时, 它检查文件是否被载入到优先的基地址上, 若是文件没有载入到优先的基地址, Windows会从新定位文件, 修改全部内存地址引用。这是极其耗时的, 由于Windows必须载入整个文件, 并修改文件中的不少字节. 此外, 这个页面文件对应的代码不能跨进程边界共享。

                     5. 较差的执行时性能: 当编译代码时, Ngen对执行环境作出的假设不会比JIT编译器的多, 这会形成Ngen产生较保守的代码, 例如, Ngen不能优化一些CPU指令。 Ngen处处插入代码来调用类的构造函数, 由于它不知道代码执行的次序, 不知道类的构造函数是否已经被调用了。 一些Ngen应用程序反而会比JIT编译的代码慢大约5%, 所以, 若是你打算使用Ngen来提升应用程序的性能, 你应该对比Ngen和非Ngen版本的应用程序, 肯定Ngen版本在实际执行时并不慢。 对于一些应用程序, 减少的工做集大小会提升性能, 所以Ngen整体上仍是会取胜。

      Ngen的利弊,须要你们本身去权衡,但对于客户端应用程序,Ngen会对于提升启动速度或者减少工做集有帮助。此外,若是Ngen被用于全部的客户端应用程序的程序集, 那么CLR就根本不须要载入JIT编译器, 从而更进一步地下降了工做集. 固然, 若是只有一个程序集不是Ngen所建立或者若是一个程序集的Ngen文件不能被使用, JIT编译器就会被载入, 应用程序的工做集将会增长。

      如何使用Ngen呢?很简单咱们只须要两个命令就能够玩转它,这两个命令是

      Ngen install filepath

      Ngen uninstall filepath

      当咱们想建立一份Ngen程序集时,只要按以下步骤作:假设E盘内有一个WindowsFormsApp.exe文件,它属于WindowsFormsApp工做集。打开命令提示符,输入“cd C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319”(目录因Windows、.Net版本而异),回车。再输入“Ngen install e:\WindowsFormsApp”,回车。这样,一份Ngen工做集就在本地建立完成了。固然想卸载它,只要输入“Ngen uninstall e:\WindowsFormsApp”,回车便可。

      固然,这只是本地Ngen工做集,要在客户机上建立,必需要在安装软件中加入Ngen代码。

相关文章
相关标签/搜索