标准IO和系统调用的效率在apue书里面介绍的很清楚了,下面测试一下。
第一步
首先建立以个100M文件
代码如下
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <fcntl.h> 4 #include <string.h> 5 #include <sys/stat.h> 6 int main(int argc, char const *argv[]) 7 { 8 if (argc != 3) { 9 fprintf(stderr, "Usage:%s <write content> <filename>\n", argv[0]); 10 exit(EXIT_FAILURE); 11 } 12 char *w = (char *)argv[1]; 13 char *filename = (char *)argv[2]; 14 int fd; 15 int n; 16 fd = open(filename, O_CREAT|O_RDWR); 17 if (fd < 0) 18 perror("open file error"); 19 struct stat statbuf; 20 fstat(fd, &statbuf); 21 int filesize; 22 filesize = statbuf.st_size/1024/1024; 23 printf("%d k\n", filesize); 24 n = strlen(w); 25 while (filesize <= 100) { 26 if (write(fd, w, n) != n) 27 perror("write error"); 28 fstat(fd, &statbuf); 29 filesize = statbuf.st_size/1024/1024; 30 31 } 32 exit(0); 33 34 }
生成 100M左右的文件
./bigfile abcd123456789 bigfile.log
第二步 编写标准IO读写代码
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 int main(int argc, char const *argv[]) 5 { 6 7 int size = atoi(argv[1]); 8 char buf[size]; 9 while (fgets(buf,size, stdin) != NULL) { 10 if (fputs(buf, stdout) == EOF) 11 perror("output error"); 12 } 13 exit(0); 14 15 }
gcc stand.c -o stand
第三步,编写系统调用读写
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <fcntl.h> 5 6 int main(int argc, char const *argv[]) 7 { 8 9 int size = atoi(argv[1]); 10 char ch[size]; 11 int n; 12 int fd; 13 //fd = open("bigfile.log", O_RDWR); 14 while ((n = read(STDIN_FILENO, &ch, size)) > 0) { 15 if (write(STDOUT_FILENO, &ch, n) != n) 16 perror("write error"); 17 } 18 exit(0); 19 20 }
gcc systemwrite.c -o systemwrite
第四步 在不同的bufsize copy 100 文件
4-1 系统调用
[root@MiWiFi-R3-srv apuetest]# time ./systemwrite 512 < bigfile.log > log.log
real 0m8.111s
user 0m0.075s
sys 0m3.891s
[root@MiWiFi-R3-srv apuetest]# time ./systemwrite 1024 < bigfile.log > log.log
real 0m5.554s
user 0m0.049s
sys 0m2.500s
[root@MiWiFi-R3-srv apuetest]# time ./systemwrite 4096 < bigfile.log > log.log
real 0m3.122s
user 0m0.002s
sys 0m1.267s
[root@MiWiFi-R3-srv apuetest]# time ./standio 8192 < bigfile.log > log.log
real 0m2.354s
user 0m0.002s
sys 0m1.059s
[root@MiWiFi-R3-srv apuetest]# time ./standio 16384 < bigfile.log > log.log
real 0m0.953s
user 0m0.002s
sys 0m0.490s
[root@MiWiFi-R3-srv apuetest]# time ./standio 32768 < bigfile.log > log.log
real 0m1.262s
user 0m0.003s
sys 0m0.810s
[root@MiWiFi-R3-srv apuetest]# time ./standio 65536 < bigfile.log > log.log
real 0m1.184s
user 0m0.002s
sys 0m0.727s
[root@MiWiFi-R3-srv apuetest]# time ./standio 131072 < bigfile.log > log.log
real 0m1.066s
user 0m0.002s
sys 0m0.579s
[root@MiWiFi-R3-srv apuetest]# time ./standio 524288 < bigfile.log > log.log
real 0m1.146s
user 0m0.004s
sys 0m0.745s
[root@MiWiFi-R3-srv apuetest]# time ./standio 5242880 < bigfile.log > log.log
real 0m1.134s
user 0m0.000s
sys 0m0.688s
可以看到bufsize 小,和 太大都会增加执行时间。
4-2 标准IO 的读写
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 512 < bigfile.log > log1.log
real 0m7.325s
user 0m0.255s
sys 0m4.629s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 1024 < bigfile.log > log1.log
real 0m2.912s
user 0m0.101s
sys 0m1.514s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 4096 < bigfile.log > log1.log
real 0m3.020s
user 0m0.143s
sys 0m1.570s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 8192 < bigfile.log > log1.log
real 0m2.946s
user 0m0.111s
sys 0m1.449s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 16384 < bigfile.log > log1.log
real 0m2.001s
user 0m0.069s
sys 0m1.179s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 32768 < bigfile.log > log1.log
real 0m1.566s
user 0m0.083s
sys 0m0.894s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 65536 < bigfile.log > log1.log
real 0m1.362s
user 0m0.168s
sys 0m0.794s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 131072 < bigfile.log > log1.log
real 0m1.237s
user 0m0.224s
sys 0m0.663s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 524288 < bigfile.log > log1.log
real 0m1.172s
user 0m0.297s
sys 0m0.662s
[root@MiWiFi-R3-srv apuetest]# time ./fstandio 5242880 < bigfile.log > log1.log
real 0m1.030s
user 0m0.366s
sys 0m0.507s
标准IO在bufsize 不同时,执行时间也相差不小。从系统调用的时间来看,bufseize越大系统调用时间就越快。
到底bufsize 多大会影响到系统调用的时间呢。
从上面的数据还是不能看出来。
能得出的结论是bufsize 确确实实在影响到了系统调用。
在允许的条件下,减少系统调用。
apue 上的结论是标准IO的有点是无需考虑缓冲以及最佳I/O长度的选择,系统调用时间几乎相同,上面的标准IO读写结果来看,系统时间在变化。
在看看标准io 但字节读写的效率
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 int main(int argc, char const *argv[]) 5 { 6 int c; 7 while ((c = getc(stdin)) != EOF) 8 if (putc(c, stdout) == EOF) 9 perror("output error"); 10 11 exit(0); 12 13 }
gcc fgetc.c -o fgetc
[root@MiWiFi-R3-srv apuetest]# time ./fgetc < bigfile.log > logfgetc.log
real 0m7.272s
user 0m1.948s
sys 0m3.656s
系统调用时间和fgets还是不一样的。和apue 上说的不一样。
原因不太清楚,有时间看看glbc 的源码吧。