【C# 线程】编译器代码优化技术 循环提升:Loop Hoisting
转载自:https://gandalfliang.github.io/2019/01/15/loop-hoisting/
Loop Hoisting
在上篇文章中,提到 Loop Hoisting ,这是一个常见的编译器优化项。我们总是能通过汇编代码等低级语言来“窥探”代码实际是怎么“指示”硬件运行的(这边文章不会涉及到详细的汇编内容,但是会用C#反编译后得到的汇编代码来辅助说明)。如果你看过我前面的几篇文章,会发现我用了大量反编译后的汇编代码来辅助说明,毕竟,千言不如实际的“证据”有说服力。
言归正传,Loop Hoisting,循环提升(粗略的翻译),编译器对循环代码中 loop-invariant 的代码提取出循环体外,防止循环结构内CPU对主存的重复读取。这很好理解,减少 CPU 与主存之间的 IO 次数,能有效提升程序的运行效率。观察下面的例子:
namespace loop_hoisting
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[] { 1, 2, 3 };
int x = 10;
int y = 11; LoopHoistTest(array, x, y);
} static void LoopHoistTest(int[] array, int x, int y)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = x + y;
}
}
}
}
很简单的一个例子,遍历列表且赋值。LoopHoistTest 函数的循环判断里,直接读取列表的长度,编译器在碰到这种情况,会对其进行优化,将对列表长度的读取进行提升(Hoist),在循环体入口处缓存列表长度,并以此为判断依据,也就是说,从汇编代码的角度,循环判断始终去寄存器中读取缓存的列表长度信息,而不是每次都到主存中读取,以此来提到运行效率。另外,x+y很明显也是一段 loop-invariant 代码,相似地,编译器会将 x+y 的值缓存在某个通用寄存器内,并以此做赋值运算。编译器优化后的代码,就相当于:
namespace loop_hoisting
{
class Program
{
static void Main(string[] args)
{
int[] array = new int[] { 1, 2, 3 };
int x = 10;
int y = 11; LoopHoistTest(array, x, y);
} static void LoopHoistTest(int[] array, int x, int y)
{
int length = array.Length;
int sum = x+y; for (int i = 0; i < length; i++)
{
array[i] = sum;
}
}
}
}
观察汇编代码:

第一个红色框选的汇编代码:
mov ebx,dword ptr [rsi+8] //将rsi寄存器值加上8的偏移量指向的主存中的值复制到ebx通用寄存器
其中rsi寄存器中的值就是主存中array的地址,偏移的8位指向length字段,这段指令将数值中的长度信息储存在ebx通用寄存器中,并且在以后的cmp指令中使用,而不是直接与主存中的内容比较。
lea ebp,[rdx+r8] //将 rdx 和 r8 寄存器中的值相加并传送到 ebp 寄存器
其中,rdx和r8寄存器分别储存着 x 和 y 的值,两者的和被储存在ebp寄存器,以后的指令都使用这个寄存器中的值,不再重复计算。
当然,并不是所有的循环代码都可以被优化,这涉及到 Loop-invariant 条件的判定,我们下篇文章再讲。
【C# 线程】编译器代码优化技术 循环提升:Loop Hoisting的更多相关文章
- Looper.loop() android线程中的消息循环
Looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用Looper.prepare()来给线程创建一个消息循环,调用Loope ...
- 简单了解一下事件循环(Event Loop)
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- 事件循环Event loop到底是什么
摘要:本文通过结合官方文档MDN和其他博客深入解析浏览器的事件循环机制,而NodeJS有另一套事件循环机制,不在本文讨论范围中.process.nextTick和setImmediate是NodeJS ...
- TMsgThread, TCommThread -- 在delphi线程中实现消息循环
http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使 ...
- TMsgThread, TCommThread -- 在delphi线程中实现消息循环(105篇博客,好多研究消息的文章)
在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供. 花了两天的事件研究了 ...
- 心智与认知(1): 反馈循环(Feedback loop)
目录: ** 0x01 反馈循环(Feedback loop) | How to see System in everyday life ** 0x02 如何像视频游戏一样剖析你的人生?| 打怪升级这 ...
- JS事件循环(Event Loop)机制
前言 众所周知,为了与浏览器进行交互,Javascript是一门非阻塞单线程脚本语言. 为何单线程? 因为如果在DOM操作中,有两个线程一个添加节点,一个删除节点,浏览器并不知道以哪个为准,所以只能选 ...
- 事件循环 event loop 究竟是什么
事件循环 event loop 究竟是什么 一些概念 浏览器运行时是多进程,从任务管理器或者活动监视器上可以验证. 打开新标签页和增加一个插件都会增加一个进程,如下图:  浏览器渲染进程是多线程,包 ...
- oracle的控制语句if和循环语句loop while for
pl/sql的控制结构if-then if-then-else if-then-elsif-else 案例1:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该雇员工资增加10% ...
随机推荐
- unity3d之public变量引发错误
public变量引发错误 在vs ide中怎么更改也无效 后来发现public里面的值一直不改变,手动改之.
- vue操作dom元素
传统的方法获取dom元素操作dom,通常是获取类名,id,属性等来获取到dom,但在vue中获取组件dom的话会有问题,请看下面代码: 控制台打印出来的结果如下,你会发现正常标签可以正常显示,但是组件 ...
- python中的rpc库
基于xml的rpc调用 rpcserver.py from xmlrpc.server import SimpleXMLRPCServer # python中类的命名方式遵循驼峰命名法 # 1. 没有 ...
- 多线程(Thread类中的方法线程名称)
1 package multithread; 2 3 /* 4 * 如何创建一个线程呢? 5 * 6 * 创建线程方式一:继承Thread类. 7 * 8 * 步骤: 9 * 1,定义一个类继承Thr ...
- 如何使用c#编写单片机程序
因为个人喜爱想研究单片机,但是不太会c,然后再找资料研究有没有其他的方法发现国外的c# nanoframework 框架可以编写单片机程序,本文我将会用自己踩过的坑来总结一些c#编写单片机的一些经 ...
- Kubernetes 证书默认1年过期时间修改
使用过的kubeadm搭建K8s集群的朋友知道,默认自动生成的证书有效期只有 1 年,因此需要每年手动更新一次证书,这种形式显然对实际生产环境来说很不友好:因此下面教给大家修改这个过期时间的终极方法. ...
- 从故纸堆里,回顾下Web技术的发展历程
通过对比这些年的计算机图书来让大家感受下前些年Web技术的发展历程. Web开发框架,目前是Spring Boot+JPA,我正好出过本书,从中大家能感受到现在的技术. <Spring Boot ...
- 带你十天轻松搞定 Go 微服务系列(七)
序言 我们通过一个系列文章跟大家详细展示一个 go-zero 微服务示例,整个系列分十篇文章,目录结构如下: 环境搭建 服务拆分 用户服务 产品服务 订单服务 支付服务 RPC 服务 Auth 验证( ...
- HowToDoInJava 其它教程 2 · 翻译完毕
原文:HowToDoInJava 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. ApacheCN 学习资源 目录 JMS 教程 JMS 教 ...
- Android Adapter基本理解
感谢大佬:https://blog.csdn.net/l799069596/article/details/47301711 Android Adapter基本理解: 我的理解是: 1.一个有许多ge ...