在.net中为什么第一次执行会慢?
众所周知.NET在第一次执行的时比第二第三次的效率要低很多,最常见的就是ASP.NET中请求第一个页面的时候要等上一段时间,而后面任意刷新响应都非常迅速,那么是什么原因导致的呢?为什么微软不解决这个问题呢?
问题
首先大家可以在心底回答这几个问题,这也是读完本文之后会陆续解决的问题。
1.生成就是编译吗?
2.既然执行过一次之后效率会高很多为什么微软不解决这样的问题呢?
3.预编译比JITCompiler的方式好吗?
效率比较

第一次执行耗费了399
第二次执行耗费了5
为什么差这么多呢?后面就让我们来揭晓。
注:单位不是ms(毫秒)
生成就是编译吗?
首先我先回答第一个问题:生成也是编译(语言编译),只不过不是编译成机器码(汇编),而是“IL”,但一般人会听到编译都联想到编译成机器码(汇编),所以大家最好叫生成。
既然在生成的时候没有编译成机器码,那么计算机是如何执行的呢?下面我们来看描述了方法首次调用的一幅图,摘自网络。

可以看出,在WriteLine下有个JITCompiler,没错就是这个函数帮我们把WriteLine编译成了机器码。
那当第二次执行的时候JITCompiler会变成本地代码,也就是说JITCompiler不会再次执行了,顺带得到的好处就是效率提升了。
既然执行过一次之后效率会高很多为什么微软不解决这样的问题呢?
为什么微软不再VS生成的时候就编译成机器码呢?
其实微软有提供相关的设置(预编译),但不推荐使用。
微软既然提供了预编译为什么不把它设为默认的呢?
这个就得跳到第三个问题咯,大家继续往下看。
预编译比默认的方式好吗?
多平台支持
再写完一个程序时(WinForm比较常见)可以发现可疑同时运行在x86和x64的平台上,那为什么x64的操作系统一开始会有那么多的x86软件兼容问题呢?

其实针对x86和x64平台的指令是有区别的,深入的我也不太了解,有大牛可以细说说。
那为什么一次生成可以同时在x64和x86上同时运行呢?
原因其实很简单:JITCompiler是在执行方法时才会将IL编译成机器码,那么微软当然有办法根据平台的差异性编译出对应的机器码。
忽略不适应代码
1: if (numberOfCPUs > 1) {
2: ...
3: }
如果主机只有一个CPU,JIT编译器不会为上述代码生成任何CPU指令,那么这样顺带的结果就是最终的代码变得更小,执行的更快(可能有人说扯淡,就算一个CPU的这段代码也不会执行啊,那么大家得考虑机器码不是面向对象的语言可能一个小小的if就会顺带很多指令)。
未来还有更多
这种优化未来只会更多,因为CLR在不停的更新。。。
抛弃预编译吗?
答案肯定是否的,预编译有自己的优势,如果你所写的代码只在一台服务器或者少个数的服务器上运行,那么完全可以针对服务器进行预编译,但面向多服务端、客户端的程序还是最好采用JIT编译。
结语
部分引自:CLR via C#(第三版)
其实我觉得.NET并不是完全的编译型语言,从JIT编译来看他也是一种解析执行语言(把IL解析成机器语言)。
在.net中为什么第一次执行会慢?的更多相关文章
- 人机大战中AlphaGo及其执子人黄士杰
2016年3月9日注定要写入围棋界的历史.IT界的历史以及科学界的历史.当天,韩国著名围棋棋手李世石VS谷歌AlphaGo的人机大战赛在韩国首尔举行.对弈的一方为拥有1200多个处理器的谷歌人工智能系 ...
- 解决Spring Cloud中Feign第一次请求失败的问题
在Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题 com.netflix.hystrix.exception.HystrixTimeoutE ...
- shell 脚本中 while 只执行一次
实例代码 while read line ; do ssh -p20002 $line -o StrictHostKeyChecking=no xxxxxxxxx done < ip.txt w ...
- 【跨域】SpringBoot跨域,拦截器中,第一次获取的请求头为NULL,发送两次请求的处理方式
背景: 在做前后端分离时,牵扯到跨域,但是已经设置了跨域 前端设置了允许携带Cookie axios.defaults.withCredentials = true; 后端也配置了跨域 浏览器端查看发 ...
- Scala中Iterator允许执行一次
背景 使用spark执行mapPartitionsWithIndex((index,iterator)=>{....}),在执行体中将iterator进行一次迭代后,再次根据iterator执行 ...
- 在内网中OWA第一次访问速度慢的问题
当网络环境为内网时,有时访问OWA站点一直卡在Office Web App 那里. 这是因为SharePoint有一个证书需要联网检索 此环境为SharePoint 2013 通过下面的三个步骤 ...
- Crontab中shell每分钟执行一次HDFS文件上传不执行的解决方案
一.Crontab -e 加入输出Log */1 * * * * /qiwen_list/upload_to_hdfs.sh > /qiwen_list/mapred.log 2>& ...
- Unity中让Update中的方法执行一次
Unity中让Update中的方法执行一次 Unity中,很多时候,代码需要放在Update中时刻监测状态,一旦状态符合,又只需要代码执行一次:其实可以通过设置控制量的方式,让代码只执行一次:方法:设 ...
- 小tips:JS中this操作执行像(object.getName = object.getName)()操作改变了this
var name = "The window"; var object = { name: "My Object", getName: function(){ ...
随机推荐
- jQuery Validate 表单验证插件----在class属性中添加校验规则进行简单的校验
一.下载插件包. 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW 访问密码 f224 二.jQuery表单验证插件----添加class属性形式的校验 <!DOCTY ...
- Java 开发环境部署
1.下载Java开发环境工具包JDK,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html 下载后,双击jdk ...
- 双向广搜 codevs 3060 抓住那头奶牛
codevs 3060 抓住那头奶牛 USACO 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description 农夫约翰被告知一头逃跑奶牛 ...
- Java虚拟机详解03----常用JVM配置参数
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- flex4 s:Datagrid <s:typicalItem
<s:DataGird <s:typicalItem 这个标签相信大家很陌生吧, 我也是今天准备讲的时候才看到,估计是 flex4.5.1 新加东西,果然摸索 了下,这个标签作用也蛮好用的 ...
- ExtJS要利用观察者模式 去实现自定义的事件
// 要利用观察者模式 去实现自定义的事件 //1:由于浏览器他自己能定义内置的事件(click/blur...) // 我们也应该有一个类似于浏览器这样的类,这个类 自己去内部定义一些事件(自定义事 ...
- 判断变量是否为json对象
var m ={a:'A'}; if(typeof m == 'object' && JSON.stringify(m).indexOf('{') == 0){//判断变量m是不是js ...
- 四、Protocol 类似java的接口
概念:是一系列方法的列表,其中声明的方法可以被任意类实现.这种模式称为代理.和JAVA接口不同的是,Protocol可以不用被实现所有的方法. 使用场景:想要监听一些按钮的操作 1声明一个协议 //& ...
- gridpanel分组汇总
[ExtJS5学习笔记]第三十节 sencha extjs 5表格gridpanel分组汇总 2015-05-31 86 本文地址:http://blog.csdn.net/sushengmi ...
- Managing the Lifecycle of a Service
service的生命周期,从它被创建开始,到它被销毁为止,可以有两条不同的路径: A started service 被开启的service通过其他组件调用 startService()被创建. 这种 ...