在了解CLR运行以前让咱们先简单了解一下IL服务器
除了编译器编译的IL代码,IL也是一种汇编语言,也就是说咱们能够直接编写IL代码,固然也有对应的IL编译器,值得一提的是对于面向CLR的其余语言,
CLR只开放了一部分功能,而IL能够访问CLR的所有功能。数据结构
前面一章咱们介绍了CLR的全部初始工做,最后在调用Main入口方法的时候,CLR须要将程序集中的IL代码转为CPU指令,也就是CLR中JIT(just-in-time)
编译器的职责,CLR会即时编译IL代码函数
即时编译:在运行的时候才会进行编译(相似懒加载)
当CLR运行并调用方法时作了以下几件事情
一、检测出全部方法中全部被引用的类型,并建立一个内部数据结构进行管理,每一个类型的方法都会记录指向名为JITComplier函数的地址,
二、在方法被调用的时候,函数会在与元数据中查找被调用的方法对应的IL代码,对其验证并将代码编译成CPU指令
三、将CPU指令存贮到动态分配的内存中
四、回到内部数据结构中,修改对应方法记录的地址,指向刚才编译好的CPU指令的地址
五、最后函数会回到内存当中去运行CPU指令工具
至此一个方法调用的所有流程就走完了,若是不终止程序(终止会将编译好的cpu指令丢弃),那么CLR在第二次调用方法时,直接在数据
结构中找到对应的内存运行CPU指令,省去了上面的二、三、4步骤性能
CLR的JIT编译器以及C#编译器对本机代码的优化
C#编译器 :
/optimize 关闭 --> 编译出的IL代码会包含许多NOP指令(no-operation 空操做)和跳转执行,vs就是利用的这些指令提供了调试的功能
/optimize 开启 --> 优化后的代码会更小,程序集也会相应变小,更方便阅读IL代码(通常估计不会有人去直接阅读IL查找问题吧)优化
JIT编译器:
在 /optimize 关闭 的状况下:
/debug - 关闭(默认) --> 有优化
/debug (+/full/pdbonly) --> 未优化:编译器会生成PDB文件帮助编译器查找到局部变量并将IL代码映射到源代码方便调试,若是指定的是
/debug : full 开关,编译器还会记录每一条IL指令生成的本机指令,但会使用额外的时间和内存
在 /optimize 开启的状况下:
/debug (-/+/full/pdbonly) --> 有优化spa
虽然编译器在优化代码的过程当中会占用额外的时间和内存,可是在实际运行阶段所带来的收益远远大于这些牺牲,而且性能上远远大于非托管代码,例如:
一、JIT编译器针对不一样的CPU优化本机代码
二、会根据机器对特定的判断进行代码优化
三、CLR会根据运行状态对代码评估并从新编译(还未实现).net
最后再来简单了解一下NGen.exe工具
NGen.exe是.net framework提供的工具,它能够将代码提早编译好,这样JIT编译器不须要在运行是编译提高性能,但其实这个工具并非很实用
一、由于NGen没法对代码进行最优的优化 --> 由于没法肯定CPU
二、对服务器提高不明显 --> 由于只是在第一次运行时有帮助,后面运行的时间时相等的
三、可能失去同步 --> 若是当前代码与执行环境不符合,那么就会重新用JIT编译debug
至此关于CLR如何与程序集工做就完成了,下一节咱们将介绍.net Framework的Framework 类库以及CTS CLS调试