1. 测量系统调用成本
使用书上给出的方法,重复调用一个简单的系统调用(执行0字节的读取)100000次,使用gettimeofday()函数测量总时间,再除以1e5,即可得到单次系统调用较为精确的时间成本,c代码如下:
//p1.c
#include <stdio.h>
#include <sys/time.h>
#include <fcntl.h>
int main() {
int fd = open("./cpu.c", O_RDONLY|O_CREAT);
if (fd == -1) {
fprintf(stderr, "open failed");
exit(1);
}
struct timeval start, end;
char buf[10];
gettimeofday(&start, NULL);
for (int i = 0; i < 1e5; ++i) read(fd, (void*)buf, 0);
gettimeofday(&end, NULL);
printf("The time cost of system call is %lf us\n", (double)(end.tv_usec - start.tv_usec) / 1e5);
close(fd);
return 0;
}
编译p1.c文件:
gcc -o p1 p1.c -Wall
执行p1,打印输出结果为:
The time cost of system call is 0.079230 us
2.测量上下文切换成本
创建两个管道,两个进程。让进程1从管道1中读数据、向管道2中写数据;让进程2向管道1中写数据、从管道2中读数据。触发进程切换的机制是,利用管道通信,若管道中此时没有数据,进程仍从该管道中读取数据,那么该进程将会被阻塞,调度器从就绪进程队列中选择一个进程进行运行。利用Linux上的sched_setaffinity()函数,可以使得进程绑定到特定的处理器上,从而确保在测量操作系统在同一个处理器上切换上下文的成本。
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
int pi1[2], pi2[2];
char buf1[30], buf2[30];
int p1, p2;
struct timeval start, end;
if ((p1 = pipe(pi1) < 0) || (p2 = pipe(pi2) < 0)) { //创建管道
fprintf(stderr, "pipe failed");
exit(1);
}
int rc = fork(); //创建子进程
cpu_set_t mask;
CPU_ZERO(&mask); //初始化set集(可用cpu集),置为空
CPU_SET(1, &mask); //向可用cpu集中添加1
for (int i = 0; i < 10; ++i) {
if (rc < 0) {
fprintf(stderr, "fork failed");
exit(1);
} else if (rc == 0) {
if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { //进程绑定到1号处理器
fprintf(stderr, "Set CPU affinity failed");
exit(1);
}
read(pi1[0], buf1, 25);
gettimeofday(&end, NULL);
printf("%ld\n", end.tv_usec - atol(buf1));
gettimeofday(&start, NULL);
sprintf(buf2, "%ld", start.tv_usec);
write(pi2[1], buf2, 25);
} else {
if (sched_setaffinity(0, sizeof(mask), &mask) == -1) { //进程绑定到1号处理器
fprintf(stderr, "Set CPU affinity failed");
exit(1);
}
gettimeofday(&start, NULL);
sprintf(buf1, "%ld", start.tv_usec);
write(pi1[1], buf1, 25);
read(pi2[0], buf2, 25);
gettimeofday(&end, NULL);
printf("%ld\n", end.tv_usec - atol(buf2));
}
}
return 0;
}
编译并执行,打印输出结果为:
158
4
3
1
1
2
1
8
2
1
1
2
1
1
3
3
2
1
2
74
取最小值,即上下文切换成本需要1us左右的时间。