网上看了很多文章,都说 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一些。