关于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% ...
随机推荐
- 【c++】计算句子中单词的平均长度
Description 编程输入一行文本,计算这行文本的单词平均长度.假设每个单词用至少一个空格或者标点(英文逗号.句号)隔开.使用C++ string类型. Input 输入一行文本,不包含数字 O ...
- 【读书笔记】iOS-手势识别
一,事件处理机制 事件是当用户手指触及屏幕,或地屏幕上滑动,或摇晃设备等时候,系统不断地把这些事件通过消息发送给应用程序对象.在iOS设备中能够捕获的事件有3种:触摸事件,移动事件和多媒体远程控制事件 ...
- Python 关于Python函数参数传递方式的一点探索
关于Python函数参数传递方式的一点探索 by:授客 QQ:1033553122 实践代码 #!/usr/bin/env python # -*- coding:utf-8 -*- __author ...
- js判断当前浏览器语言类型
console.log(window.navigator.language.slice(0, 2)); 得到的是zh
- [Android] ubuntu 下不识别 Android 设备
之前的android手机给家人用了,手里现在有一个旧手机,调试过程又出现不识别的问题,这次要记录一下. 首先,需要把手机开发者选项打开,在设置里对着android版本或者型号多点几次,就会打开. 原文 ...
- selenium元素定位(Java)
1.使用findElement方法定位元素 findElement()方法:当开始寻找符合指定条件的元素时,它将查询整个DOM,然后返回第一个找到的匹配元素. By id:通过元素ID属性定位 ...
- 机器学习实战(Machine Learning in Action)学习笔记————10.奇异值分解(SVD)原理、基于协同过滤的推荐引擎、数据降维
关键字:SVD.奇异值分解.降维.基于协同过滤的推荐引擎作者:米仓山下时间:2018-11-3机器学习实战(Machine Learning in Action,@author: Peter Harr ...
- genymotion 模拟器内安装软件 the app contains ARM native code and your devices cannot run ARM instructions
问题如图: 解决方法: 下载一个Genymotion-ARM-Translation软件,安装到模拟器中就好了
- webservice偶尔报黄页,解决方案
在system.web节点里加以下代码 <webServices> <protocols> <add name="HttpSoa ...
- 在Emacs中使用git操作
在Emacs中使用git操作 1.安装 magit 插件 2.安装后开始使用 3.使用方法: . 使用 M-x:magit-status 打开当前仓库查看基本信息 .使用 ? 键查看magit命令绑定 ...