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

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

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

3.Native代码

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

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

Advantage:1.提高启动速度, 因为代码已经编译成Native代码, 所以在运行时就不需要编译了。

2.减少应用程序的工作集,如果一个程序集会被同时载入到多个进程/Appdomain,,在这个程序集上运行Ngen能减少应用程序的工作集。因为Ngen会将IL编译为Native代码后,保存到单独的文件夹。这个文件夹能在同一时刻对多个进程空间起作用,且允许代码共享。所以, 每个进程/AppDomain不必为自己拷贝一份代码。

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

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代码。

Ngen生成Native代码实战及优缺点分析的更多相关文章

  1. RocketMQ延迟消息的代码实战及原理分析

    RocketMQ简介 RocketMQ是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的.高可靠.万亿级容量.灵活可伸缩的消息发布与订阅服务. 它前身是MetaQ,是阿里基于Kafka ...

  2. 【腾讯Bugly干货分享】React Native项目实战总结

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/577e16a7640ad7b4682c64a7 “8小时内拼工作,8小时外拼成长 ...

  3. Android Native 代码NDK开发学习笔记

    引用:http://www.kunli.info/2011/08/21/android-native-code-study-note/ JNI,全称Java Native Interface,是用于让 ...

  4. React Native 项目实战-Tamic

    layout: post title: React Native 项目实战 date: 2016-10-18 15:02:29 +0800 comments: true categories: Rea ...

  5. JDK和Cglib实现动态代理实例及优缺点分析

    Spring AOP使用的核心技术是动态代理,说到动态代理就不得不和设计模式中的代理模式联系起来,通过代理模式我们可以对目标类进行功能增强,在某个方法的执行前后增加一些操作,例如计算方法执行效率.打印 ...

  6. Javascript中,实现类与继承的方法和优缺点分析

    Javascript是一种弱类型语言,不存在类的概念,但在js中可以模仿类似于JAVA中的类,实现类与继承 第一种方法:利用Javascript中的原型链 //首先定义一个父类 function An ...

  7. TaintDroid剖析之Native方法级污点跟踪分析

    1.Native方法的污点传播 在前两篇文章中我们详细分析了TaintDroid对DVM栈帧的修改,以及它是如何在修改之后的栈帧中实现DVM变量级污点跟踪的.现在我们继续分析其第二个粒度的污点跟踪—— ...

  8. Scala 深入浅出实战经典 第39讲:ListBuffer、ArrayBuffer、Queue、Stack操作代码实战

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  9. .net postsharp编译时生成的代码?

    使用PostSharp进行AOP框架设计:一个简单的原型   AOP已经不是一个什么新名词了,在博客园使用关键字搜索可以查出n多条关于AOP的介绍,这里就不再赘述了. 在Bruce Zhang's B ...

随机推荐

  1. MFC之RTTI与动态创建

    本人能力.精力有限,所言所感都基于自身的实践和有限的阅读.查阅,如有错误,欢迎拍砖,敬请赐教——博客园:钱智慧. 在说RTTI之前需要明白c++中类静态成员的初始化特点:类的静态数据成员需要在类体外显 ...

  2. 使用 Windows PowerShell 管理Windows Azure映像

    你可以使用 Azure PowerShell 模块中的 cmdlet 管理可供你的 Azure 订阅使用的映像.这包括 Azure 提供的映像以及你上载的映像.对于某些映像任务,你还可以使用 Azur ...

  3. Mozilla NPAPI开发示例之一(VS2012 + Win7(64位))

    入门级的NPAPI开发. NPAPI & NPRuntime 简介 Netscape Plugin Application Programming Interface (NPAPI) NPAP ...

  4. java_list<String> string[]拼接json

    private String getJsonStr(List<String> jsonKeyList, String[] values){ String jsonStr = "{ ...

  5. Oracle学习过程(随时更新)

    1.入门 实用的一些查询语句: 查询用户所有表注释 select * from user_tab_comments 条件查询 根据两个值查询 select*from table where 字段 in ...

  6. 用HiveDB横向切分MySQL数据库

    HiveDB是一个用来横向切分mysql数据库的开源框架,构建一个高性能和可扩展的基于mysql的系统需要大量的系统设计经验和良好的代码的实现,一个比较好的策略是将你的数据横向切分在多个server上 ...

  7. 用来理解 Java 编程语言的 8 个图表

    原文地址: http://www.oschina.net/news/44438/top-8-diagrams-for-understanding-java 很多时候,一张图比你说 1000 个字能更有 ...

  8. tr 命令 操作字符串中字符 删除替换 等

    ip=$(cat ${path}initOauth/initinfo.txt |awk '{if(NR==1)print $0;}'|tr -d '\r'); tr命令可以对来自标准输入的字符进行替换 ...

  9. git 设置

    系统乱码 项目中的编码统一设置为UTF-8编码. 设置系统的语言设置为 zh_UTF-8,把 export LANG=zh_CN.UTF-8 保存到~/.profile文件里. $ env|grep ...

  10. cocos2dx js文件加密为jsc文件

    发布产品,脚本代码是必须要加密的 偶尔会出现编译后的jsc无法运行,或者某些jsb自定义的函数找不到, 最好将require("jsb.js")的全部内容整合到一个文件,然后编译j ...