0%

测量系统调用成本

测量成本的工具

使用 gettimeofday() 这个典型时钟函数来测量时间成本,返回自1970-01-01 00:00:00到现在所经历的秒数,调用两次该函数通过相减的方式获取时间差。

根据函数的定义:此函数在sys/time.h>

1
int gettimeofday(struct timeval *, struct timezone *);

定义了两个结构体,分别记录时间和时区

1
2
3
4
5
6
7
8
9
struct timeval {undefined
time_t tv_sec;
suseconds_t tv_usec;
};//存储秒和微秒

struct timezone {undefined
int tz_minuteswest;
int tz_dsttime;
};//记录时区

使用举例 : 测试其时间精度是否可以达到定义中声明的微秒级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
struct timeval start,end;
int i = 10;
gettimeofday(&start, NULL);
for(i=0;i<10;++i) {
gettimeofday(&start, NULL);
gettimeofday(&end, NULL);
printf("%ld\n", end.tv_usec - start.tv_usec);
printf("%ld %ld\n", end.tv_usec, start.tv_usec);
}
gettimeofday(&end, NULL);
return 0;
}

这是在空系统调用测试中连续调用 gettimeofday()函数,如果精确度可以达到微秒 级别,那么两次连续调用获取的时间相减应该近似于0

执行结果如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0
157238 157238
0
157275 157275
0
157278 157278
1
157282 157281
0
157285 157285
0
157288 157288
0
157291 157291
1
157295 157294
0
157298 157298
0
157301 157301

基本可以确定在微秒级别

注意

一般情况下,系统调用的时间成本是在 ns的级别,所以即使可以达到微秒级别,也要通过多次测量取平均值的办法才可以尽可能的实现准确。


测量系统调用的时间成本

这里使用简单的 read() 函数来测量调用的成本 , 测试程序的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

int main()
{
int n = 10;
while (n--)
{
int fd = open("./6.2.c", O_RDONLY);
int i;
char buf[10];
struct timeval start, end;
if (fd == -1)
{
fprintf(stderr, "file open failed!\n");
exit(1);
}
gettimeofday(&start, NULL);
for (i = 0; i < 10000; ++i)
{
read(fd, buf, 0); //为了让程序结束,把read的第二个参数改为0,这样就可以尽可能测量纯粹的系统调用耗时
}
gettimeofday(&end, NULL);
printf("%d :万次的平均结果: %lf\n", 10 - n, (1000000 * (end.tv_sec - start.tv_sec) + end.tv_usec - start.tv_usec) * 1.0 / 10000); //强制转换为double
close(fd);
}
return 0;
}

测试程序的结果如下

1
2
3
4
5
6
7
8
9
10
1 :万次的平均结果: 0.583100
2 :万次的平均结果: 0.598400
3 :万次的平均结果: 0.594100
4 :万次的平均结果: 0.595600
5 :万次的平均结果: 0.601000
6 :万次的平均结果: 0.615700
7 :万次的平均结果: 0.606900
8 :万次的平均结果: 0.589100
9 :万次的平均结果: 0.595500
10 :万次的平均结果: 0.584900

从多次运行万次平均结果看,对于 read 函数,系统调用的时间约为 0. 6 微秒。