关于for,while,dowhile效率测试
引言
大家都知道每种循环对应的效率是不同的,书中都说在循环中使用减法的效率是比加法的效率高的,具体情况是怎么样,我们将详细列出各循环的执行效率问题。本文通过查看汇编代码比较各循环的效率以及i++,++i,i--,--i在循环中使用的效率问题,仅供抛砖引玉,测试平台为intel i5 4440,编译器为gcc-4.8.2
测试代码1
此段代码我们主要测试在i--,--i,i++,++i的情况下,for循环、dowhile循环、while循环之间的执行效率情况
#include <stdio.h> /* 用于测试i--的while,for,dowhile循环情况 */
void minus1 (void)
{
int i = ; /* i-- while循环 */
while (i--)
; i = ; /* i-- dowhile循环 */
do
;
while (i--); /* i-- for循环 */
for (i = ; i != ; i--)
;
} /* 用于测试--i的while,for,dowhile循环情况 */
void minus (void)
{
int i = ; /* --i while循环 */
while (--i)
; i = ; /* --i dowhile循环 */
do
;
while (--i); /* --i for循环 */
for (i = ; i != ; --i)
;
} /* 用于测试i++的while,for,dowhile循环情况 */
void plus1 (void)
{
int i = ; /* i++ while循环 */
while (i++ < )
; i = ; /* i++ dowhile循环 */
do
;
while (i++ < ); /* i++ for循环 */
for (i = ; i < ; i++)
;
} /* 用于测试++i的while,for,dowhile循环情况 */
void plus (void)
{
int i = ; /* ++i while循环 */
while (++i < )
; i = ; /* ++i dowhile循环 */
do
;
while (++i < ); /* ++i for循环 */
for (i = ; i < ; ++i)
;
} int main (int argc, char * argv[])
{
return ;
}
测试代码1所生成的汇编代码如下:
#include <stdio.h> void minus1 (void)
{
4004ed: push %rbp
4004ee: e5 mov %rsp,%rbp
int i = ;
4004f1: c7 fc 0a movl $0xa,-0x4(%rbp) # i = while (i--) # while (i--)
4004f8: nop # 空指令
4004f9: 8b fc mov -0x4(%rbp),%eax # eax = i 主循环
4004fc: 8d ff lea -0x1(%rax),%edx # edx = rax - (rax的低32位为eax) 主循环
4004ff: fc mov %edx,-0x4(%rbp) # i = edx 主循环
: c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
: f3 jne 4004f9 <minus1+0xc> # 不等于0则跳转至4004f9 主循环
; i = ;
: c7 fc 0a movl $0xa,-0x4(%rbp) # i = do
;
while (i--); # do ... while (i--);
40050d: 8b fc mov -0x4(%rbp),%eax # eax = i 主循环
: 8d ff lea -0x1(%rax),%edx # edx = rax - (rax的低32位为eax) 主循环
: fc mov %edx,-0x4(%rbp) # i = edx 主循环
: c0 test %eax,%eax # 等同于(i & i), 如果i不等于0,则结果也不为0 主循环
: f3 jne 40050d <minus1+0x20> # 不等于0则跳转至40050d 主循环 for (i = ; i != 0; i--) # for (i = 10; i != 0; i--)
40051a: c7 fc 0a movl $0xa,-0x4(%rbp) # i =
: eb jmp <minus1+0x3a> # 跳转至400527
: 6d fc subl $0x1,-0x4(%rbp) # i = i - 主循环
: 7d fc cmpl $0x0,-0x4(%rbp) # i与0进行比较 主循环
40052b: f6 jne <minus1+0x36> # 比较结果不等于0则跳转至400523 主循环
;
} void minus (void)
{
40052f: push %rbp
: e5 mov %rsp,%rbp
int i = ;
: c7 fc 0a movl $0xa,-0x4(%rbp) while (--i) # while (--i)
40053a: 6d fc subl $0x1,-0x4(%rbp) # i = i - 主循环
40053e: 7d fc cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
: f6 jne 40053a <minus+0xb> # 比较结果不等于0则跳转至40053a 主循环
; i = ;
: c7 fc 0a movl $0xa,-0x4(%rbp) do
;
while (--i); # do ... while (--i);
40054b: 6d fc subl $0x1,-0x4(%rbp) # i = i - 主循环
40054f: 7d fc cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
: f6 jne 40054b <minus+0x1c> # 比较结果不等于0则跳转至40054b 主循环 for (i = ; i != 0; --i) # for (i = 10; i != 0; --i)
: c7 fc 0a movl $0xa,-0x4(%rbp) # i =
40055c: eb jmp <minus+0x33> # 跳转至400562
40055e: 6d fc subl $0x1,-0x4(%rbp) # i = i - 主循环
: 7d fc cmpl $0x0,-0x4(%rbp) # i与0比较 主循环
: f6 jne 40055e <minus+0x2f> # 比较结果不等于0则跳转至40055e 主循环
;
} void plus1 (void)
{
40056a: push %rbp
40056b: e5 mov %rsp,%rbp
int i = ;
40056e: c7 fc movl $0x0,-0x4(%rbp) while (i++ < ) # while (i++ < )
: nop
: 8b fc mov -0x4(%rbp),%eax # eax = i 主循环
: 8d lea 0x1(%rax),%edx # edx = rax + (rax的低32位为eax) 主循环
40057c: fc mov %edx,-0x4(%rbp) # i = edx 主循环
40057f: f8 cmp $0x9,%eax # eax与9比较 主循环
: 7e f2 jle <plus1+0xc> # 比较结果不成立则跳转至400576 主循环
; i = ;
: c7 fc movl $0x0,-0x4(%rbp) do
;
while (i++ < ); # while (i++ < 10);
40058b: 8b fc mov -0x4(%rbp),%eax # eax = i 主循环
40058e: 8d lea 0x1(%rax),%edx # edx = rax + (rax的低32位为eax) 主循环
: fc mov %edx,-0x4(%rbp) # i = edx 主循环
: f8 cmp $0x9,%eax # eax与9比较 主循环
: 7e f2 jle 40058b <plus1+0x21> # 比较结果不成立则跳转至40058b 主循环 for (i = ; i < 10; i++) # for (i = 0; i < 10; i++)
: c7 fc movl $0x0,-0x4(%rbp) # i =
4005a0: eb jmp 4005a6 <plus1+0x3c> # 跳转至4005a6
4005a2: fc addl $0x1,-0x4(%rbp) # i = i + 主循环
4005a6: 7d fc cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
4005aa: 7e f6 jle 4005a2 <plus1+0x38> # 比较结果不成立则跳转至4005a2 主循环
;
} void plus (void)
{
4005ae: push %rbp
4005af: e5 mov %rsp,%rbp
int i = ;
4005b2: c7 fc movl $0x0,-0x4(%rbp) while (++i < ) # while (++i < )
4005b9: fc addl $0x1,-0x4(%rbp) # i = i + 主循环
4005bd: 7d fc cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
4005c1: 7e f6 jle 4005b9 <plus+0xb> # 比较结果不成立则跳转至4005b9 主循环
; i = ;
4005c3: c7 fc movl $0x0,-0x4(%rbp) do
;
while (++i < ); # while (++i < 10);
4005ca: fc addl $0x1,-0x4(%rbp) # i = i + 主循环
4005ce: 7d fc cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
4005d2: 7e f6 jle 4005ca <plus+0x1c> # 比较结果不成立则跳转至4005b9 主循环 for (i = ; i < 10; ++i) # for (i = 0; i < 10; ++i)
4005d4: c7 fc movl $0x0,-0x4(%rbp) # i =
4005db: eb jmp 4005e1 <plus+0x33> # 跳转至4005e1
4005dd: fc addl $0x1,-0x4(%rbp) # i = i + 主循环
4005e1: 7d fc cmpl $0x9,-0x4(%rbp) # i与9比较 主循环
4005e5: 7e f6 jle 4005dd <plus+0x2f> # 比较结果不成立则跳转至4005dd 主循环
;
}
可以从汇编代码得出如下表格
while主循环语句数 |
do...while主循环语句数 |
for主循环语句数 | |
i-- | 5 | 5 | 3 |
--i | 3 | 3 | 3 |
i++ | 5 | 5 | 3 |
++i | 3 | 3 | 3 |
小结
可以从表中得出结论:循环效率最高也需要执行3条汇编语句,而最慢需要5条汇编语句,使用i--和i++进行循环控制时,不同的循环结构所对应的汇编代码量不同,最少的为for循环,只需要3条汇编指令,最多的为while循环,需要5条汇编指令,而当使用--i和++i进行循环控制时,无论哪一种循环结构执行效率都一样是最优的,都只需要3条代码,而无论使用i--,--i,i++,++i中哪一种,for循环的效率应该是最高的,都只用了3条汇编代码。
关于for,while,dowhile效率测试的更多相关文章
- NHibernate Demo 和 效率测试
本文关于NHibernate的Demo和效率测试,希望对大家有用. 1.先去官网下载Nhibernate 2.放入到项目中并建立Helper类 private static ISession _Ses ...
- 关于 pgsql 数据库json几个函数用法的效率测试
关于 pgsql 数据库json几个函数用法的效率测试 关于pgsql 几个操作符的效率测试比较1. json::->> 和 ->> 测试方法:单次运行100次,运行10个单次 ...
- Python_线程、线程效率测试、数据隔离测试、主线程和子线程
0.进程中的概念 三状态:就绪.运行.阻塞 就绪(Ready):当进程已分配到除CPU以外的所有必要资源,只要获得处理机便可立即执行,这时的进程状态成为就绪状态. 执行/运行(Running)状态:当 ...
- 进程池原理及效率测试Pool
为什么会有进程池的概念? 当我们开启50个进程让他们都将100这个数减1次减到50,你会发现特别慢! 效率问题,原因: 1,开辟内存空间.因为每开启一个进程,都会开启一个属于这个进程池的内存空间,因为 ...
- postgresql-int,bigint,numeric效率测试
在postgresql9.5的时候做过一个测试就是sum()的效率最终的测试结果是sum(int)>sum(numeric)>sum(bigint)当时比较诧异为啥sum(bigint)效 ...
- ORM for Net主流框架汇总与效率测试
框架已经被越来越多的人所关注与使用了,今天我们就来研究一下net方面的几个主流ORM框架,以及它们的效率测试(可能会有遗漏欢迎大家讨论). ORM框架:Object/Relation Mapping( ...
- 纯PHP Codeigniter(CI) ThinkPHP效率测试
最近一直想做一个技术类的新闻站点,想做的执行效率高些,想用PHP做,一直纠结于用纯PHP做还是用CI或者THINKPHP.用纯PHP效率高,缺点 n多,比如安全方面.构架方面等等等等:用CI.thin ...
- Python--day39--进程池原理及效率测试
#为什么要有进程池的概念 #效率 #每次开启进程都要创建一个属于这个进程的内存空间 #寄存器 堆栈 文件 #进程过多 操作系统调度进程 # #进程池 #python中的 先创建一个属于进程的池子 #这 ...
- 关于pgsql 几个操作符的效率测试比较
关于pgsql 几个操作符的效率测试比较1. json::->> 和 ->> 测试方法:单次运行100次,运行10个单次取平均时间.测试结果:->> 效率高 5% ...
随机推荐
- Spider-one
1. 爬虫是如何采集网页数据的: 网页的三大特征: -1. 每个网页都有自己的 URL(统一资源定位符)地址来进行网络定位. -2. 每个网页都使用 HTML(超文本标记语言)来描述页面信息. -3. ...
- npm 走 privoxy 代理经常出现 shasum check failed 的解决办法
今天在下载一个比较大的项目,经常 shasum check failed ,太烦了,于是想切淘宝源,分别尝试 nrm 切换和传递 --registry ,结果都出现 Unexpected end of ...
- 关于input的焦点事件
关于input的焦点事件 $(".scanf_integral").focus(function(){//获取焦点//获取焦点后触发的事件 }) $(".scanf_in ...
- web全栈架构师[笔记] — 03 html5新特性
HTML5新特性 一.geolocation PC端 精度比较低 通过IP库定位 移动端 通过GPS window.navigator.geolocation 单次 getCurrentPositio ...
- loadrunner 场景设计-制定负载测试计划
by:授客 QQ:1033553122 场景设计-制定负载测试计划 步骤1.分析应用程序 你应该对硬件和软件组建,系统配置和典型的使用场景很熟悉.这些应用程序的分析保证你在使用loadrunner进行 ...
- 最新安全狗 apache v4.0 sql注入 bypass
前言 最近没事学习一下 waf 的 bypass , 本文介绍下 bypass 安全狗的笔记.个人感觉 bypass 的总思路(正则匹配型 waf)就是利用各种语法特性来逃避正则(当然要保证语法正确性 ...
- Android Context类
一.Context类的使用场景 ①.创建Application对象时,而且整个app公用一个Application对象 ②.创建Service对象时 ③.创建Activity对象时 二.应用程序共有几 ...
- JavaScript大杂烩1 - 理解JavaScript的类型系统
随着硬件水平的逐渐提高,浏览器的处理能力越来越强大,本人坚信,客户端会越来越瘦,瘦到只用浏览器就够了,服务端会越来越丰满:虽然很多大型的程序,比如3D软件,客户端仍然会存在,但是未来的主流必将是浏览器 ...
- asp.net mvc中的后台验证
asp.net mvc的验证包含后台验证和前端验证.后台验证主要通过数据注解的形式实现对model中属性的验证,其验证过程发生在model绑定的过程中.前端验证是通过结合jquery.validate ...
- Mysqli面向对象操作数据库
Mysqli面向对象操作数据库 首先配置一下数据库: 接着用PHP中的Mysqli扩展库面向对象查询这个数据表. 操作分为以下几个步骤: 连接数据库 操作数据库 处理结果 关闭资源 <?php ...