作为一种代码指令平台,Microsoft .NET比微软公司先前推出的其他技术平台要来得更为复杂。由于.NET提供了对多种编程语言以及(在理论上说)多重平台的支持,这就需要在传统的两个代 码层添加一个中间代码层。在这里,传统的两层分别是源代码层和编译后的本机代码层。新加的代码层给.NET平台带来了额外的灵活性,不过,反过来却又增加 了系统的复杂性。此外,由于这一新代码层的出现,一连串的新型应用程序部署选项也首次展现在了程序员的面前。

.NET之与众不同:MSIL

在Microsoft .NET框架内,应用程序可以用好多种高级程序语言编写、创建,例如VB.NET、C#乃至COBOL .NET等等都可以编写.NET应用程序。而通过每一种遵守.NET规范的编程语言所编写的程序代码首先都得通过一种初始编译步骤从源代码变成.NET的 公共标准语言:MSIL(微软中介语言:Microsoft Intermediate Language)。MSIL自身是一种完整的、和对象相关的语言,只有它才可能创建出应用程序。为了大致了解MSIL的一些有关情况,你可以参看“通过 MSIL语言了解CLR的运行原理”一文。.NET应用程序是以MSIL的形式出现的,只有在程序执行的时候才通过即时编译器(JIT)被编译为本机代 码。

.NET的编译过程:从源代码到本机指令

只要装载了assembly代码就会进行JIT编译,可见这是一种汇编级的编译(了解更多assembly技术的细节请参看“Assembly—治愈
“DLL地狱”的良方?”一文)。在编译过程中,JIT编译器一旦首次遭遇对象的索引就会装载匹配对象各个方法声明的对应程序。这样,以后调用方法的时候

就会编译其IL,而方法的对应根程序则被方法的编译后代码的地址所取代。这一过程在每次方法被首次调用的时候进行,产生的本机代码则被缓冲以便会话过程中
下次装载assembly代码的时候可以被使用。显然,这样的指令系统相比传统的编译语言需要更大的处理能力,不过其要求也没有你想象的那么高。

在这里必须澄清一个普遍误解的错误概念,那就是不少人认为.NET应用程序是解释型而非编译型的程序。另外,还有这样的常见错误认识:JIT编译的代码存

储在磁盘上并且可以为同一应用程序执行。虽然这样做也不是不可以,但是,你很快就会明白,这可不是缺省的编译方案。应用程序的IL代码实际上在每次应用程
序运行的时候都会被重新编译为本机代码。

两种编译器

事实上,JIT编译器分成两种(经济编译器和普通编译器),而且它们生来也不是平等的。经济JIT编译器代表了运行一个.NET应用程序所需要的最少功
能,它直接用对等的本机代码取代每一条MSIL指令,不进行任何优化从而也带来更少的系统负载。这也意味着它主要应用在内存等资源比较紧张的平台上。

另一方面,普通JIT编译器则是缺省的运行时配置,它会对其产生的代码进行即时优化。这样做无形中给予了.NET超出传统预编译语言的一个优点:预编译语

言只能对其处理的代码将要运行于其上的平台做一番大致的事前估计。JIT编译器可以经过准确调节达到当前运行时状态,结果可以完成一些预编译语言无法完成
的工作:

·更高效地利用和分配CPU寄存器
·在适当的情况下实施低级代码优化,比如常量重叠、拷贝复制、取消范围检查、取消常规副表达式以及方法内联等
·在代码执行期间监控当前的物理和虚拟内存需求从而更高效地利用内存
·产生特定的平台指令以准确、充分地利用实际的处理器模式

.NET编译的结果就是JIT所带来的额外负载要求并没有产生显著的性能损失。

性能选项

这就是说,每次运行应用程序时MSIL就会被JIT编译。记住,这就是常识了,然后,根据以上内容中说明的原理,在开始启动应用程序以及首次使用非核心功能的时候显然会导致低于优化级的系统性能表现。那么你又该采取什么措施把这种负面影响降低到最小呢?

微软公司的对策是为我们提供了一种名为Pre-JIT的编译器(也被称做本机映像生成器:Native Image
Generator,程序名因此是Ngen.exe)。从表面上看,至少它也算是应付任何性能问题的一项治疗手段。Pre-JIT编译器在运行时之前被调
用,在安装时,它会把全部assembly形式的MSIL编译为本机代码。这种本机代码随后存储在全局assembly缓存(Global
Assembly Cache)的某一个特殊部分供以后使用,这样就完全绕过了JIT编译过程。

乍看之下,这样做应该是解决先前的问题了,对客户端代码而言尤其如此。但是,你还记得吗?普通JIT在编译MSIL的时候实施了大量的即时优化操作。而许

多此类的优化操作,尤其是那些牵扯到寄存器和存储器使用的优化,都是由系统的当前需求所驱动的。所以,批量编译assembly代码的举措就会阻止这些优

化的进行从而在实际上产生出运行更慢的最终代码。在你采用这个法子之前,微软的建议是,比照普通编译下的当前条件,把你的JIT和Ngen版本设置为目标
平台上的同一汇编级。

.NET 代码编译过程的更多相关文章

  1. 【转】Java代码编译过程简述

    转载:https://blog.csdn.net/fuzhongmin05/article/details/54880257. 代码编译是由Javac编译器来完成,流程如下图1所示: 图1 Javac ...

  2. java代码编译过程

    简单随笔 java程序需要先编译成class文件然后才能执行,由于是编程成立机器代码,虚拟机加载内存的时候更快的执行. java文件编译成class文件步骤如下: 1)词法分析,检查每一个关键字单词是 ...

  3. ios oc 代码 转换为 c++ 描述代码编译过程

    clang -rewrite-objc main.m #import <Foundation/Foundation.h> #import <objc/runtime.h> // ...

  4. python代码是解释型语言,为什么还有编译过程?

    Python 代码在运行前,会先编译(翻译)成中间代码,每个 .py 文件将被换转成 .pyc 文件,.pyc 就是一种字节码文件,它是与平台无关的中间代码,不管你放在 Windows 还是 Linu ...

  5. 【lombok】使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法

    错误如题:使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法 报错如下: 解决方法: 1.首先查看你的lombok插件是否下载安 ...

  6. C语言代码区错误以及编译过程

    C语言代码区错误 欲想了解C语言代码段会有如何错误,我们必须首先了解编译器是如何把C语言文本信息编译成为可以执行的机器码的. 背景介绍 测试使用的C语言代码 导入标准库,定义宏变量,定义结构体,重命名 ...

  7. GCC编译过程

    以下是C程序一般的编译过程: gcc的编译流程分为四个步骤,分别为:· 预处理(Pre-Processing) 对C语言进行预处理,生成*.i文件.· 编译(Compiling) 将上一步生成的*.i ...

  8. Linux系统GCC常用命令和GCC编译过程描述

    前言: GCC 原名为 GNU C 语言编译器(GNU C Compiler),因为它原本只能处理 C语言.GCC 很快地扩展,变得可处理 C++.后来又 扩展能够支持更多编程语言,如Fortran. ...

  9. 如何提升代码编译的速度 iOS

    前阵子有遇到代码编译速度慢的问题,特别是在swift和object-c混编的过程中问题很突显. 网上找到一篇蛮好的文章里面又一些解决方法 推荐一下 http://www.open-open.com/l ...

随机推荐

  1. 关于C#迭代器

    >1 IEnumerator与IEnumerable IEnumerator与IEnumerable两个接口是用于实现迭代器的接品只要实现了IEnumerable就可以用foreach,linq ...

  2. c++读入之 -- 汉字读入遇到的问题

    好吧,课题和汉语处理有关,于是就要求用c++来读入汉字进行处理. 首先使用wchar_t字符即宽字符,然后这样定义: #include <cstdio> #include <cwch ...

  3. python中的urlencode与urldecode

    当url地址含有中文,或者参数有中文的时候,这个算是很正常了,但是把这样的url作为参数传递的时候(最常见的callback),需要把一些中文甚至'/'做一下编码转换. 所以对于一些中文或者字符,ur ...

  4. HDU 4050 wolf5x 概率dp 难度:1

    http://acm.hdu.edu.cn/showproblem.php?pid=4050 题意: 现在主角站在0处,需要到达大于n的位置 主角要进入的格子有三种状态: 0. 不能进入 1. 能进入 ...

  5. C语言中 scanf 和 printf 的小要点

    1 scanf_s需指定%c 个数 h short l long关键字 * 不赋给任何值 W 指定读入宽度 转换字符 a 读浮点值(c99) A 读浮点值(c99) c 读单字符 d 读十进制数 i ...

  6. mysql 远程连接

    4.现在如果用你电脑上的终端进行MySQL连接时,有可能出现如下错误: MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXX ...

  7. 学好C++必须要注意的十八个问题

    转自  http://blog.chinaunix.net/uid-7396260-id-2056691.html 一.#include "filename.h"和#i nclud ...

  8. 交互式报表和工作报表控件Stimulsoft Reports.Fx for Java

    Stimulsoft Reports.Fx for Java是一款Java平台下的报表工具控件,可以为您的应用程序添加交互式报表和工作报表.Java技术可以用于不同的平台.不同的操作系统和不同的硬件, ...

  9. Android ViewPager 里有子ViewPager的事件冲突

    在Android应用中有时候要用到类似网易新闻左右滑动页面且页面里又有左右滑动的图片功能,我不知道网易是怎么实现的,本人的做法是外面的BaseFragmentActivity布局就是TabViewPa ...

  10. @Param注解在mybatis中的使用以及传入参数的几种方式(转)

    第一种: Dao层的方法 <span style="font-size:12px;">Public User selectUser(String name,String ...