测试c语言函数调用性能因素之测试三

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

操作:

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;

三,参数个数

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

四,结论:

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<=0)return p_recorde;
 int i_rand[array_len];
 int i=0;
 clock_t start_time,end_time;
 start_time=clock();
 for(i=0;i<array_len;i++)
 {
    i_rand[i]=rand(); 
 }
 end_time=clock();
 p_recorde+=(long)(end_time-start_time);
 call_back(call_num-1,typeone,typetwo,typethree,p_recorde);
}
void main(int argc,char *argv[])
{
  int loop_num=atoi(argv[1]),call_num=atoi(argv[2]);
  long p_recorde=0,sum=0;
  clock_t start_time,end_time;
  start_time=clock();
  int i;
  for(i=0;i<loop_num;i++)
  {
   sum_loop+=call_back(call_num,0,0,0,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的差即为函数调用的时间总消耗;

时间: 2024-10-26 21:15:22

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

测试c语言函数调用性能因素之测试二

函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作. 操作: 1,               调用函数帧指针(函数参数,局部变量,栈帧状态值,函数返回地址)入栈,栈指针自减 2,               保存调用函数的状态数据入寄存器 3,               被调用函数帧指针入栈,执行当前的被调用函数 4,               被调用函数执行结束,退栈,返回到调用函数的帧指针,从寄存

测试c语言函数调用性能因素

函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作. 操作: 1,               调用函数帧指针(函数参数,局部变量,栈帧状态值,函数返回地址)入栈,栈指针自减 2,               保存调用函数的状态数据入寄存器 3,               被调用函数帧指针入栈,执行当前的被调用函数 4,               被调用函数执行结束,退栈,返回到调用函数的帧指针,从寄存

使用fio测试磁盘I/O性能报告

浪潮存储服务器SA5212 I/O基准性能测试报告 1.测试目的 本次测试针对的是浪潮存储服务器SA5212的I/O基准性能,测试维度主要分为磁盘RAID5和RAID10下的读写吞吐量,包括顺序读写,随机读写 2.服务器软硬件环境 系统环境:Centos 7.2 硬件资源:系统盘4*500G SSD,RAID10:存储磁盘12*6T SATA,7200转 3.测试工具 fio - Flexible IO Tester 主要参数说明: filename=/dev/sdb   #测试文件名称,通常选

PHP 使用Apache 中的ab 测试网站的压力性能

打开Apache服务器的安装路径(我用的是 WampServer),在bin目录中有一个ab.exe的可执行程序,它就是要介绍的压力测试工具. 在Windows系统的命令行下,进入ab.exe程序所在目录,执行ab.exe程序.注意直接双击无法正确运行. d:(回车/进入D盘) cd wamp\bin\apache\Apache2.4.4\bin(回车/进入 bin目录) ab(回车/) 如果看到下列一些帮助信息就说明成功启动ab     开始启动ab 压力测试 ab -n 5000 -c 20

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

黑盒测试 黑盒测试把产品软件当成是一个黑箱子,只有出口和入口,测试过程中只要知道往黑盒中输入什么东西,知道黑盒会出来什么结果就可以了,不需要了解黑箱子里面是如果做的. 即测试人员不用费神去理解软件里面的具体构成和原理,只要像用户一样看待产品就可以了. 例如银行转账功能,不需要知道转账的具体实现代码是怎样工作的,只需要把自己想象成各种类型的用户,模拟多种转账情况看系统是否能正常转账即可. 但是仅仅像用户一样去测试又是不够的.如果只做黑盒测试,必然是存在一定的风险的. 例如某个安全性较高的软件系统,

【Java 语言生态篇】Junit 测试单元

01 概述 JUnit是一个由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework).Junit测试是白盒测试.JUnit有它自己的JUnit扩展生态圈.多数Java的开发环境都已经集成了JUnit作为单元测试的工具.[1] JUnit是一个开放源代码的Java测试框架,用于编写和运行可重复的测试.他是用于单元测试框架体系xUnit的一个实例(用于java语言).它包括以下特性: 1.用于测试期望结果的断言(Asser

C# 集合性能比较(代码测试)

using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Table_And_List { public class Program { public static

编写自动测试c语言程序的shell脚本

目前经常用vim编写一些c语言程序,写好了程序一般都得进行一些测试,当然我们可以进行一些常规的手动测试.心里一想,如果能够用shell脚本编写一个能自动测试c语言程序就好了. 为了试一试这样的想法,找了一个c语言程序题目: [一球从 100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10 次落地时,共经过多少米?第10 次反弹多高? ] 根据这样的要求我编写了一个解决这个问题的程序: #include <stdio.h> #include <stdlib.h> #

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

Linux 平台上的性能工具有很多,眼花缭乱,长期的摸索和经验发现最好用的还是那些久经考验的.简单的小工具.系统性能专家 Brendan D. Gregg 在最近的 LinuxCon NA 2014 大会上更新了他那个有名的关于 Linux 性能方面的 talk (Linux Performance Tools) 和幻灯片. 和 Brendan 去年的 talk比较,今年增加了测试和优化两部分.下面的三张图片分别总结了 Linux 各个子系统以及监控.测试.优化这些子系统所用到的工具. 监控 测