网上看了很多文章,都说 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 }
View Code

经不断调整 第 10 行 buff 的大小,测得结果如下:

buff大小 Bytefread执行时间fread系统调用次数read执行时间read系统调用次数
81920.0017217750.001416775
40960.00248215480.0018041548
204800243115480032103094
102400306515480054473836

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一些。

01-15 19:30