在应用程序开发过程中,开发者都力求写出更加高效的代码。但是当你想手工为C#编译器优化代码时,你的种种优化可能反倒会阻碍JIT进行更加高效的优化。因此,我们最好尽可能的写出最清晰的代码,将优化工作交给JIT编译器去完成。

  在.NET平台下开发程序的开发者都应该知道:.NET运行时将调用JIT编译器来将C#编译器生成的IL翻译成机器码。JIT不会在程序刚开始的时候就完全翻译所有的IL代码,CLR根据函数的粒度来逐一进行JIT编译。没有被调用的函数根本不会被JIT编译,因此将那些非常重要的逻辑分解成更多的小方法要比把所有逻辑放在一起形成大型复杂函数更有效率。例如下面的代码:

 1     public string BuildMsg(bool takeFirstPath)
 2     {
 3         StringBuilder msg = new StringBuilder();
 4
 5         if (takeFirstPath)
 6         {
 7             msg.Append("A problem occurred.");
 8             msg.Append("\nThis is a problem.");
 9             msg.Append("imagine much more text");
10         }
11         else
12         {
13             msg.Append("This Path is not so bad.");
14             msg.Append("\nIt is only a minor inconvenience.");
15             msg.Append("Add more detailed diagnostics here.");
16         }
17         return msg;
18     }

在第一次调用BuildMsg时,if-else两个分支都将被JIT编译。而实际上仅需要编译其中的一个分支就足够了,我们可以拆分这个方法,对其进行优化,下面是优化后的代码:

View Code

 1         public string BuildMsg(bool takeFirstPath)
 2         {
 3             if (takeFirstPath)
 4             {
 5                 return FirstPath();
 6             }
 7             else
 8             {
 9                 return SecondPath();
10             }
11         }
12
13         public string FirstPath()
14         {
15             StringBuilder msg = new StringBuilder();
16
17             msg.Append("A problem occurred.");
18             msg.Append("\nThis is a problem.");
19             msg.Append("imagine much more text");
20
21             return msg.ToString();
22         }
23
24         public string SecondPath()
25         {
26             StringBuilder msg = new StringBuilder();
27
28             msg.Append("This Path is not so bad.");
29             msg.Append("\nIt is only a minor inconvenience.");
30             msg.Append("Add more detailed diagnostics here.");
31
32             return msg.ToString();
33         }
34     }

这时候两个方法可以根据需要再进行JIT编译,而不必在第一次调用BuildMsg方法是进行。我们可以看出:更小的函数让JIT编译器更方便的根据需要进行编译,而不是将时间浪费在不急于一时使用的代码上。对于switch语句中的每个case中的代码,这个规则的影响更明显。

寄存器的优化

  小而简单的方法会让JIT更容易的进行寄存器的选择工作,即选择哪个局部变量可以存放在寄存器中,而不是栈上。越少使用局部变量,也就让JIT编译器能够更方便的找到最适合放在寄存器的那一些。而越小的函数包含的局部变量也越少,也就更方便JIT对寄存器进行优化

内联的优化 

  内联表示把函数体替换到函数被调用的位置。由JIT编译器负责决定哪些方法应该被内联,当内联可以有效提高效率时,JIT编译器将自动执行。不过内联的标准并不是固定的,且当前的规则也不能保证将来不会发生变化,此外,是否内联完全由JIT自己决定。不过我们可以使用下面的特性选项通知JIT不要内联某个方法:

1         [MethodImpl(MethodImplOptions.NoInlining)]

  方法越简单就越适合内联。不过虚方法和包含ctry/catch代码块的方法将不会被内联。内联也改变了:代码在执行时才会被JIT编译 这一原则。所以在.NET平台下编程我们的责任应该就是尽量编写短小精悍的方法,而为你的算法生成高效的机器码是C#编译器和JIT编译器的责任。

小节:

将C#代码翻译为可执行的机器码有两个步骤:1.C#编译器将代码生成为IL,并放在程序集中。2.JIT再根据需要逐一为方法(或是一组方法,如果涉及内联)生成机器码。短小的方法让JIT编译器能够更好的平摊编译的代价。短小的代码也更适合内联。方法除了短小之外,简化控制流程也很重要,控制的分支越少JIT编译器也更容易选择找到最适合放在寄存器中的变量。因此,编写短小精悍的代码不但影响代码的可读性,也影响到程序运行的效率。

转载于:https://www.cnblogs.com/IPrograming/archive/2012/10/08/Effective_CSharp_11.html

《Effective C#》读书笔记——条目11:理解短小方法的优势C#语言习惯相关推荐

  1. Effective C++读书笔记 摘自 pandawuwyj的专栏

    Effective C++读书笔记(0)       Start   声明式(Declaration):告诉编译器某个东西的名称和类型,但略去细节.   std::size_t numDigits(i ...

  2. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  3. more effective c++和effective c++读书笔记

    转载自http://bellgrade.blog.163.com/blog/static/83155959200863113228254/,方便日后自己查阅, More Effective C++读书 ...

  4. Effective Java读书笔记(二)

    Effective Java 读书笔记 (二) 创建和销毁对象 遇到多个构造器参数时要考虑使用构建器 创建和销毁对象 何时以及如何创建对象? 何时以及如何避免创建对象? 如何确保它们能够适时地销毁? ...

  5. Effective Java 读书笔记(七):通用程序设计

    Effective Java 读书笔记七通用程序设计 将局部变量的作用域最小化 for-each 循环优于传统的 for 循环 了解和使用类库 如果需要精确的答案请避免使用 float 和 doubl ...

  6. 202314读书笔记|《孩子们的诗》——简单的语言,击中每个人心中的诗意

    202314读书笔记|<孩子们的诗>--简单的语言,击中每个人心中的诗意 <孩子们的诗>作者果麦.这本书中的诗都是孩子们写的,虽然他们或许并不认为自己写的是诗.每个人都想一直做 ...

  7. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  8. PMP读书笔记(第11章)

    大家好,我是烤鸭:     今天做一个PMP的读书笔记. 第十一章 项目风险管理 项目风险管理 项目风险管理的核心概念 项目风险管理的趋势和新兴实践 裁剪考虑因素 在敏捷或适应型环境中需要考虑的因素 ...

  9. 电磁兼容工程(Electromagnetic compatibility engineering Herry Ott )读书笔记-- 章11 数字电路电源分布

    目录 11  数字电路电源分布 11.1 电源去耦 11.2 电源管脚的瞬态电流 11.2.1 瞬态负载电流 11.2.2  动态内部电流 11.2.3 瞬态电流的傅里叶频谱 11.2.4 总共的瞬态 ...

最新文章

  1. android 教程 最新版,Android最新版本开发环境搭建图文教程
  2. p点到(a,b)点两所在直线的垂点坐标及p点是否在(a,b)两点所在直线上
  3. c语言宏定义_掌握C语言,中文编程不是梦
  4. 消息(6)——WCF,构建简单的WCF服务,MTOM编码
  5. linux sudo命令全称,linux sudo命令的概念与使用
  6. java中p.name_spring如何使用命名空间p简化bean的配置
  7. mysql批量插入跟更新_Mysql批量插入和更新的性能-问答-阿里云开发者社区-阿里云...
  8. html网页视频播放器代码,HTML网页制作视频播放器现成代码
  9. 年龄、性别2022 cnn算法笔记
  10. MUI初体验 模仿微信页面
  11. Android开发,实现摇一摇功能
  12. 程序员新手上路第一步
  13. 试输出斐波那契数列的前10项
  14. 快手2020校园招聘秋招笔试--工程B试卷 订正
  15. java rhino 运行 js_Rhino -- 基于java的javascript实现
  16. PGSQL(学习与操作)
  17. 在进行CMOS设置时也会出现死机
  18. 呼叫中心管理系统的描述
  19. 《STM32从零开始学习历程》——I2C固件库
  20. 安卓 获取屏幕像素 密度 计算真是高度

热门文章

  1. a Line Segment Detector
  2. 在Eclipse中配置Tomcat服务
  3. 制作liveusb实现centos6.2全自动无人职守安装
  4. 论文笔记之:Graph Attention Networks
  5. 社交系统/社群系统ThinkSNS+ alpha.2 版本发布!
  6. 【负载均衡】揭开F5 BIG-IP的神秘面纱(一)
  7. linux下c++實現簡單的生產者消費者隊列模式
  8. 谷歌浏览器跨域报错解决办法
  9. LeetCode 451. Sort Characters By Frequency
  10. 13.2. Mount partition