网上看了很多文章,都说 fread 比 read 读取数据更快云云,今天在我的 mac 上做了一个小测试,结果比较意外

1 #include <stdio.h>
2 #include <unistd.h>
3 #include <time.h>
4 #include <fcntl.h>
5
6 void test_fread(char *buff, int num);
7 void test_read(char *buff, int num);
8
9 int main() {
10 char buff[100];
11 test_fread(buff, sizeof(buff));
12 test_read(buff, sizeof(buff));
13 }
14
15 void test_fread(char *buff, int num) {
16 clock_t start, finish;
17 double duration;
18 start = clock();
19
20 FILE *fp;
21 char filename[] = "a.txt";
22 fp = fopen(filename, "r");
23 int i=0;
24 while(1) {
25 i++;
26 fread(buff, num, 1, fp);
27 if(feof(fp)) {
28 break;
29 }
30 }
31 fclose(fp);
32
33 finish = clock();
34 duration = (double)(finish - start) / CLOCKS_PER_SEC;
35 printf( "%f seconds\n", duration );
36 }
37
38 void test_read(char *buff, int num) {
39 clock_t start, finish;
40 double duration;
41 start = clock();
42
43 int fp;
44 char filename[] = "a.txt";
45 fp = open(filename, O_RDONLY);
46 int i = 0;
47 while(read(fp, buff, num)>0){
48 i++;
49 };
50 close(fp);
51
52 finish = clock();
53 duration = (double)(finish - start) / CLOCKS_PER_SEC;
54 printf( "%f seconds\n", duration );
55 }
经不断调整 第 10 行 buff 的大小,测得结果如下:
| buff大小 Byte | fread执行时间 | fread系统调用次数 | read执行时间 | read系统调用次数 |
| 8192 | 0.001721 | 775 | 0.001416 | 775 |
| 4096 | 0.002482 | 1548 | 0.001804 | 1548 |
| 2048 | 002431 | 1548 | 003210 | 3094 |
| 1024 | 003065 | 1548 | 005447 | 3836 |
fread是自带缓冲区(在我的mac上测试结果为4096B)
当 sizeof(buff) >= 4096 时,系统使用 sizeof(buff) 作为缓冲区大小。系统调用的次数 = 待读取字节数 / sizeof(buff)
当 sizeof(buff) < 4096 时,系统使用 sizeof(buff) 作为缓冲区大小。系统调用的次数 = 待读取字节数 / 4096
而 read 的计算公式就比较简单了~ 系统调用的次数 = 待读取字节数 / sizeof(buff)
PS:测试环境为 mac,系统调用次数可以通过命令查看 sudo dtruss -a ./a
总结:
当buff设置的比较小时,fread方法由于具有更大的缓冲区,系统调用次数变少,效率相比于 read 更快。
当buff设置的比较大时,fread方法与read方法具有了相同大小的缓冲区,系统调用次数相同。但由于 fread 是在 read 基础上的封装,做了更多的操作,效率相比于 read 更慢。
效率相同时的buff值,应该小于4096B一些。
