【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% ...
随机推荐
- HashSet 实现类
HashSet 实现类 通过 HashCode 判断元素是否存在,若存在则不添加,否则添加以此实现唯一性 常用方法 Modifier and Type Method and Description b ...
- jetson-nano opencv基础使用
前言: jetson nano前一篇给大家介绍了学习的一些思路和资料,今天继续给大家分享一篇在jetson nano使用opencv的文章. OpenCV的全称是Open Source Compute ...
- Vue3.2中的setup语法糖,保证你看的明明白白!
vue3.2 到底更新了什么? 根据原文内容的更新的内容主要有以下 5 块: 1.SSR:服务端渲染优化.@vue/server-renderer包加了一个ES模块创建, 与Node.js解耦,使在非 ...
- Android开发-数据库代码编写
数据库代码主要是查找 package com.example.Utils.database; import android.annotation.SuppressLint; import androi ...
- Hello,find!
Hello,find! 前言 余幼时,每至除夕,爆竹声声,如雷贯耳,醒于梦中,便知春节将至.与兄长二三人,执摔炮六七只, 玩耍于廷中.出门罢,廷中白雪覆于黄土之上.二三尺之外,见犬窝,余之爱犬趴于其中 ...
- 集合remove()方法相关问题
学习集合的过程中,了解到一个有关于remove()方法的有关特性,特此记录 首先remove方法的格式: collection.remove(Object o); 这是指对集合collection内的 ...
- JVM学习五:性能监控工具
一.系统性能监控 系统性能工具用于确定系统运行的整体状态,基本定位问题所在. Linux – uptime • 系统时间 • 运行时间 n 例子中为7分钟 • 连接数 n 每一个终端算一个连接 • 1 ...
- 创建spring boot项目并添加多个模块时,启动报 错误: 找不到或无法加载主类
最近建个项目发现启动报,找不到或无法加载主类,想想肯定是自己配置出问题了,经过排查确实出问题了,(根pom中的bulid为移到子模块中去导致的),下面演示下正确的创建子模块的步奏 1. 创 ...
- 电脑预装Office2016打开Word时点击保存弹出“word无法启动转换器RECOVR32.CNV”对话框问题的修复方法
感谢大佬:https://blog.csdn.net/qq_41969790/article/details/85161701 1.问题描述:电脑预装的Office2016,家庭和学生版正版.每次打开 ...
- .NET 云原生架构师训练营(权限系统 代码实现 ActionAccess)--学习笔记
目录 开发任务 代码实现 开发任务 DotNetNB.Security.Core:定义 core,models,Istore:实现 default memory store DotNetNB.Secu ...