函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作。

操作:

1,               调用函数帧指针(函数参数,局部变量,栈帧状态值,函数返回地址)入栈,栈指针自减

2,               保存调用函数的状态数据入寄存器

3,               被调用函数帧指针入栈,执行当前的被调用函数

4,               被调用函数执行结束,退栈,返回到调用函数的帧指针,从寄存器中恢复当时状态数据

5,               继续执行调用函数,直至结束

即整个调用操作有一个压栈出栈,保存和恢复状态数据的过程。而系统栈内存是有默认的固有大小。有多少次函数调用就会分配多少栈帧。故,函数调用性能影响有如下因素:

1,函数递归层数;

2,参数个数(参数签名所占内存大小)

2.1同类型不同参数个数;

2.2同参数个数不同参数类型;

2.3同参数类型同参数个数,但参数类型所占内存大小不同;

3,函数栈大小,即函数局部变量所占栈大小。

为了测试C语言函数调用性能(时间消耗)因素,编写了一个简单程序运行在如下环境中:

Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz  memery size:7833700 kB(7.47GB)

在函数调用的开始与结束处,用time.h中的clock()函数返回CPU时钟计时单位数(下表中的starttime和endtime),用durationtime=endtime-starttime表示函数调用的时间消耗。如下:

clock_t  starttime=clock();

函数调用…

clock_t  endtime=clock();

//除以CLOCKS_PER_SEC,得到以秒为单位的时间结果

double durationtime=(double)(endtime-starttime)/CLOCKS_PER_SEC;//表示函数调用占用cpu的时间,不包括子进程或者printf等的操作的时间

注:clock()记录的是进程占用cpu的时间,精确度为微秒;详细讲解clock()函数的网址:http://site.douban.com/199048/widget/notes/12005386/note/253542964/

一.函数递归层数(循环1000000次)

栈(字节)

参数(字节)

递归次数

总函数调用时间消耗(秒)

每循环函数调用时间消耗(微秒)

每次函数调用平均时间消耗(纳秒)

1024

24

10

2.9

2.9

290

1024

24

20

5.713

5.713

285.65

1024

24

30

9.025

9.025

300.83

1024

24

50

16.0767

16.0767

321.534

1024

24

80

21.79

21.79

272.375

1024

24

100

30.73

30.73

307.3

1024

24

200

66.24

66.24

331.2

注:平均每次函数调用时间消耗=durationtime/调用层数/ 循环次数

每循环函数调用时间消耗=durationtime/ 循环次数

函数调用根据不同的调用层数不同的时间平均消耗,如下折线图:

图1

每次函数调用平均时间消耗,如下折线图:

图2

结论:1,在参数所占内存相同和函数栈大小相同的情况下,函数调用的时间消耗随着函数调用层数增加而增加;如图1;

2,在参数所占内存相同和函数栈大小相同的情况下,每次函数调用的时间消耗大概在300纳秒左右;如图2;

二,函数栈大小

循环次数

栈(字节)

参数

(字节)

递归次数

总函数调用时间消耗(秒)

每循环函数调用时间消耗(微秒)

平均每次函数调用(纳秒)

1000000

16

24

50

9.4

9.4

184

1000000

32

24

50

9.37

9.37

187.4

1000000

64

24

50

9.5

9.5

190

1000000

128

24

50

10.415

10.415

208.3

1000000

256

24

50

11.805

11.805

236.1

1000000

512

24

50

14

14

280

1000000

1024

24

50

16.0767

16.0767

321.534

1000000

2048

24

50

18.42

18.42

368.4

注:平均每次函数调用时间消耗=durationtime/调用层数/ 循环次数

每循环函数调用时间消耗=durationtime/ 循环次数

函数调用根据不同的调用层数不同的时间平均消耗,如下折线图:

图3

每次函数调用平均时间消耗,如下折线图:

图4

结论:1,在函数参数相同和函数调用层数相同的情况下,函数调用时间消耗随函数栈大小的增加而增加;如图3;

2,在函数参数相同和函数调用层数相同的情况下,每次函数调用时间消耗随函数栈大小的增加而增加;如图4;

三,参数个数

栈(字节)

参数

(字节)

递归次数

总函数调用时间消耗(秒)

每循环函数调用时间消耗(微秒)

平均每次函数调用(纳秒)

1024

24

50

16.0767

16.0767

321.5

1024

36

50

16.245

16.245

324.9

1024

48

50

16.345

16.345

326.9

1024

60

50

15.915

15.915

318.3

1024

72

50

14.29

14.29

285.8

1024

84

50

15.76

15.76

315.2

1024

96

50

15.14

15.14

302.8

1024

108

50

13.975

13.975

279.5

1024

120

50

16.68

16.68

333.6

1024

144

50

15.37

15.37

307.4

1024

180

50

14.42

14.42

288.4

1024

192

50

14.62

14.62

292.4

注:平均每次函数调用时间消耗=durationtime/调用层数/ 循环次数

每循环函数调用时间消耗=durationtime/ 循环次数

函数调用根据不同的函数参数大小的时间平均消耗,如下折线图:

每次函数调用平均时间消耗,如下折线图:

结论:  经过前几次的函数测试,虽然存在误差,但是仍然可以得出参数对于函数调用的时间消耗的影响,在于参数所占内存大小;函数传参存在两种方式:值传参和引用传参;两种方式在一般情况下,不会占用过多的内存;故,在一般情况下,参数对函数调用的时间消耗的影响不明显;

四,结论:

1,在函数参数大小为24字节和函数栈大小为1024字节的情况下,递归50次的函数时间消耗为16.0767微秒,可以粗略得出每次函数调用(压栈出栈)的时间消耗为320纳秒左右;

思路:1,函数参数大小:函数参数分为值传参和引用传参(参数的指针);一般值传参为常用的值类型,这样的参数一般不会占用过多的内存;引用参数是参数地址也不会占用过多内存;所以在一般情况下,函数参数对函数调用时间消耗影响不大;

2,计数:循环1000000次函数递归,是为了想提高数据的精确性和便于计算;1秒=1000000微秒;

3,递归层数:选择可能常规下递归的层数(24--35)

4,函数栈大小:按照以太网的最大字节1500字节,选择在1024字节左右做以上实验;

代码:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define array_len 256
typedef struct {
int typeone;
int typetwo;
}struct_type;
long call_back(int call_num,int typeone,int typetwo,int typethree,long p_recorde)
{
if(call_num<=)return p_recorde;
int i_rand[array_len];
int i=;
clock_t start_time,end_time;
start_time=clock();
for(i=;i<array_len;i++)
{
i_rand[i]=rand();
}
end_time=clock();
p_recorde+=(long)(end_time-start_time);
call_back(call_num-,typeone,typetwo,typethree,p_recorde);
}
void main(int argc,char *argv[])
{
int loop_num=atoi(argv[]),call_num=atoi(argv[]);
long p_recorde=,sum=;
clock_t start_time,end_time;
start_time=clock();
int i;
for(i=;i<loop_num;i++)
{
sum_loop+=call_back(call_num,,,,p_recorde);
}
end_time=clock();
double duration_time=(double)(end_time-start_time)/CLOCKS_PER_SEC-(double)sum_loop/CLOCKS_PER_SEC;
printf("sum=%f duration=%f\n",sum_loop,duration_time);
}

代码思路:1,为了减少数据cache命中的影响,在每次函数调用中用了rand()获取随机数,并记录时间消耗a;

2,记录函数调用的时间总消耗b,b-a的差即为函数调用的时间总消耗;

测试c语言函数调用性能因素之测试三的更多相关文章

  1. 进行app性能和安全性测试的重要性

    如何让用户感觉App运行速度更快呢,这需要对App进行性能测试.限制App性能的因素按照App的系统结构分为App自身和App需要用到的后台服务. 测试App连接网络的速度 一般采用在模拟Mock环境 ...

  2. 入门级----黑盒测试、白盒测试、手工测试、自动化测试、探索性测试、单元测试、性能测试、数据库性能、压力测试、安全性测试、SQL注入、缓冲区溢出、环境测试

    黑盒测试 黑盒测试把产品软件当成是一个黑箱子,只有出口和入口,测试过程中只要知道往黑盒中输入什么东西,知道黑盒会出来什么结果就可以了,不需要了解黑箱子里面是如果做的. 即测试人员不用费神去理解软件里面 ...

  3. 集群搭建完成简要测试集群(性能)带宽与IOPS

    集群搭建好之后网络,raid卡策略,磁盘都会影响集群的性能.为了避免因上述问题使得集群的性能受到影响,我们依次进行测试,最后得到基本的集群性能. 网络 首先是网络,ceph集群一大堆让人摸不着头脑的问 ...

  4. Linux 性能监控、测试、优化工具

    Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 ...

  5. 三张图看遍Linux 性能监控、测试、优化工具

    Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 ...

  6. (太强大了) - Linux 性能监控、测试、优化工具

    转: http://www.vpsee.com/2014/09/linux-performance-tools/ Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经 ...

  7. Web 应用性能和压力测试工具 Gor - 运维生存时间

    Web 应用性能和压力测试工具 Gor - 运维生存时间 undefined 无需花生壳,dnspod实现ddns - 推酷 undefined

  8. [转载]Linux 性能监控、测试、优化工具

    Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 ...

  9. Webbench、ab命令:做压力测试的工具和性能的监控工具

    DDOS攻击:???DDOS概述:分布式拒绝服务(DDoS:Distributed Denial of Service)攻击,指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目 ...

随机推荐

  1. [笔记]--Sublime Text 2使用技巧

    Sublime个人喜好设置: 在打开个人设置页面Preferences >> Settings - User,加入以下内容: { , //TAB键,4个空格 "translate ...

  2. Microsoft Visual Studio 语言切换

    事情的起因是需要安装本地的中文帮助,OS以及Viusal Studio都安装的英语版本. 其实需要安装的安装Viusal Studio的中文语言包即可. 通过工具选项可以达到以下的对话框 可以通过下载 ...

  3. hdu1007

    Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some ...

  4. bzoj 1862/1056 [HAOI2008]排名系统

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1862 很恶心的 一道题,我也不晓得自己是第几次写这题了%>_<%. 写了两种方 ...

  5. JavaScript高级程序设计之函数性能

    setTimeout 比 setInterval 性能更好 // 取代setInterval setTimeout(function self () { // code goes here setTi ...

  6. lvs keepalived 安装配置详解

    前段时间看了一篇文章,lvs做负载均衡根F5差不多,说实话不怎么相信,因为F5没玩过,也无法比较.F5相当的贵,真不是一般企业能负担的起的.负载均衡软件也用过不少,nginx,apache,hapro ...

  7. 跨域访问-需要设置HTTP响应标头设置

    跨域访问-需要设置HTTP响应标头设置 前提:服务端网站的配置(被请求的网站) 1.需要在IIS服务器站点的功能视图中设置HTTP响应标头: 2.双击“HTTP响应标头”进入设置界面 3.点击右侧添加 ...

  8. debain上安装mono3.4.0和jexus5.5.2

    今天折腾了四个小时才把这个正确安装上,特此记录下.特别感谢群友的支持. 在VMware上新安装了Debain7.5,具体细节不复述了. 一.更新系统 #apt-get update #apt-get ...

  9. 解决vs2013不能添加控制器的步骤

    点击:vs2013 更新,更新完以后,再重启下电脑就可以正常使用了

  10. C6011 正在取消对 null 指针的引用