CLR执行模型

编译器将C#/F#/VB.net源代码和资源文件打包为程序集。程序集内包含托管的模块和资源文件。托管的模块中PE32/PE32+头文件记载了与本机CPU代码有关的信息。若是为纯IL代码的模块,PE32/PE32+一般被忽略。CLR头一般记录了CLR版本、Main方法的信息以及模块的信息和一些数据,咱们可使用CLRVer.exe命令查询到CLR版本,参数为-all所有,进程ID指定进程。架构

咱们能够在Visual Studio设置目标平台信息:并发

IL代码虽然被称为一种汇编,可是看起来彷佛IL比常说的x86汇编简单不少。这种代码将会在程序第一次(而非首次)执行的时候首先读取目标的IL代码而后生成机器码而后修改目标节点的引用指向生成的机器码,当机器码生成结束后程序执行的就是机器码,由于全部的引用都被修改指向了即时生成的机器码。因此托管代码编写的程序仅在第一次执行(而非首次)的时候慢一点,然后就能全速运行。ide

这种即时编译(JIT)的技术Java目前也在使用,彷佛咱们看起来使用JIT技术会致使程序性能有点糟糕,但实际上效率可能比本身写的非托管代码的效率还高。咱们都知道编译器在编译时期会执行优化操做让程序的运行速度更快,可是编译器编译出来的程序可能在某一具体架构上不一样型号的处理器运行,为了确保不出现Intel Pentium、Intel Core i三、Intel Core i五、Intel Core i七、Intel Atom、AMD Opteron等奇葩的版本出现,那么编译器将会以最小处理器指令集编译,这样兼容性确保了,可是新的指令集的优点彷佛就没有利用到。函数

JIT在编译的时候可以知道某台计算机是否具备新的指令集可使用,一旦可用那么它会使用新的指令集,这样,利用新的指令集就可能带来速度的提高。工具

同时对于自己不能执行的代码(永假),JIT能够选择不予编译,因此在相似要求AMD处理器的IL代码段在程序运行的时候并不会被编译为机器码。这样亦可提供速度的提高。性能

因此本身的非托管代码的编写能力没有达到必定程度,托管的代码可能效率更高。优化

.NET也提供了NGen.exe工具来编译IL代码为机器码并保存为一个文件,首次加载的时候会检查该文件是否符合运行要求的版本,若是符合那么能够直接运行该文件而避免JIT,可是这样可能丧失JIT带来的优点,由于NGen.exe生成的代码不得不考虑最小运行环境。ui

若是有多处理器,那么可使用System.Runtime.ProfileOptimization类来优化。它会让CLR检查程序运行时哪些方法被JIT编译,并将结果记录到一个文件。程序再次启动时,就用其余线程并发编译这些方法。这样应用程序运行得更快,由于多个方法并发编译,并且是在应用程序初始化时编译,而不是在用户和程序交互时才“即时”编译。加密

至于有人为了保护本身的知识产权使用NGen.exe生成的机器代码发布,实际上是不能的。纵使NGen.exe生成了一份机器码,可是基于.NET的程序依然会随附一份IL汇编代码以确保在机器码出现问题的时候不会致使程序Crash。.net

因为.NET利用了JIT,如今的.NET反编译的反编译后的代码质量至关高,因此咱们经常使用的保护知识产权的办法是代码混淆。使用代码混淆器将本身写的程序混淆加密,加大反编译后阅读的难度。有趣的是彷佛这些反编译工具(ILDASM.EXE)除外都不能将F#编写的程序文件正确逆向工程。曾尝试使用F#写过一个SqlHelper动态连接库,代码混淆后再使用了三款反编译工具都没能正确逆向出F#代码,即便逆向出来的C#代码也只有函数名而不包含函数体,在整个导出文件夹内的文件中没可以找到函数体。因此若是依然想使用.NET来撰写且不但愿透露代码逻辑的,能够尝试F#这门语言。

前面说道NGen.exe产生的文件是不能够发布给用户的,可是针对大型程序咱们仍是能够利用NGen.exe来优化的,固然这里的大型程序不包括Web应用程序,由于Web应用程序仅在第一次访问的时候须要JIT,然后就不须要JIT了。使用Managed Profile Guided Optimization工具来检查启动的时候须要执行那些东西,而后反馈给NGen.exe优化产生的本机代码镜像,发布前使用MPGO.exe走一边流程后将profile文件整合进程序集,NGen.exe将会利用它来建立更佳的本机镜像。

相关文章
相关标签/搜索