本文為https://www.byvoid.com/zhs/blog/fast-readfile的驗證性文章
---------------------------------------------------------------------------
首先生成一千萬個隨機數
1 #include<cstdio> 2 #include<ctime> 3 #include<cstdlib> 4 int main () 5 { 6 freopen("data.txt","w",stdout); 7 srand(time(0)); 8 for(int i=0;i<10000000;i++) 9 printf("%d ",rand()); 10 return 0; 11 }
我用重定向把數據導出到"data.txt"了。
然后,用scanf來讀取數據,並計時
1 #include<cstdio> 2 #include<ctime> 3 int a[10000000]; 4 int main () 5 { 6 int start = clock(); 7 freopen("data.txt","r",stdin); 8 for(int i=0;i<10000000;i++) 9 scanf("%d",&a[i]); 10 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 11 }
執行之后,使用時間為1.18s,相比於原文的2.01秒,縮短了一截,然后測試一下使用cin輸入的情況,代碼如下:
1 #include<cstdio> 2 #include<ctime> 3 #include<iostream> 4 int a[10000000]; 5 int main () 6 { 7 int start = clock(); 8 freopen("data.txt","r",stdin); 9 for(int i=0;i<10000000;i++) 10 std::cin>>a[i]; 11 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 12 }
cin的使用時間為4.67s,比scanf更長,但是相比於原文的6.38s還是短得多。
然后取消cin與stdin之間的同步之后,代碼如下:
1 #include<cstdio> 2 #include<ctime> 3 #include<iostream> 4 int a[10000000]; 5 int main () 6 { 7 int start = clock(); 8 std::ios::sync_with_stdio(false); 9 freopen("data.txt","r",stdin); 10 for(int i=0;i<1000000;i++) 11 std::cin>>a[i]; 12 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 13 }
時間大幅縮短,為1.24s,與scanf很接近了。
然后按原文測試讀入整個文件,代碼如下:
1 #include<iostream> 2 #include<ctime> 3 #include<cstdio> 4 const int MAXN = 10000000; 5 const int MAXS = 60*1024*1024; 6 int numbers[MAXN]; 7 char buf[MAXS]; 8 9 void analyse(char *buf, int len =MAXS) 10 { 11 int i; 12 numbers[i=0]=0; 13 for(char *p=buf;*p && p-buf<len;p++) 14 if(*p == ' ') 15 numbers[++i]=0; 16 else 17 numbers[i]=numbers[i]*10+*p-'0'; 18 } 19 20 void fread_analyse() 21 { 22 freopen("data.txt","rb",stdin); 23 int len = fread(buf,1,MAXS,stdin); 24 buf[len]='\0'; 25 analyse(buf,len); 26 } 27 28 int main () 29 { 30 int start = clock(); 31 fread_analyse(); 32 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 33 return 0; 34 }
時間如原文一般,大幅縮短,我這里測試得到0.37s,使用read測試,代碼如下:
#include<iostream> #include<ctime> #include<cstdio> #include<unistd.h> #include<fcntl.h> const int MAXN = 10000000; const int MAXS = 60*1024*1024; int numbers[MAXN]; char buf[MAXS]; void analyse(char *buf, int len =MAXS) { int i; numbers[i=0]=0; for(char *p=buf;*p && p-buf<len;p++) if(*p == ' ') numbers[++i]=0; else numbers[i]=numbers[i]*10+*p-'0'; } void read_analyse() { int fd = open("data.txt",O_RDONLY); int len = read(fd,buf,MAXS); buf[len]='\0'; analyse(buf,len); } int main () { int start = clock(); read_analyse(); printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); return 0; }
測試時間為0.31s,有所進步,不過不是非常明顯。
調用mmap,代碼如下:
1 #include<iostream> 2 #include<ctime> 3 #include<cstdio> 4 #include<unistd.h> 5 #include<fcntl.h> 6 #include<sys/mman.h> 7 const int MAXN = 10000000; 8 const int MAXS = 60*1024*1024; 9 int numbers[MAXN]; 10 char buf[MAXS]; 11 12 void analyse(char *buf, int len =MAXS) 13 { 14 int i; 15 numbers[i=0]=0; 16 for(char *p=buf;*p && p-buf<len;p++) 17 if(*p == ' ') 18 numbers[++i]=0; 19 else 20 numbers[i]=numbers[i]*10+*p-'0'; 21 } 22 23 void mmap_analyse() 24 { 25 int fd = open("data.txt",O_RDONLY); 26 int len = lseek(fd,0,SEEK_END); 27 char *mbuf = (char *) mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,0); 28 analyse(mbuf,len); 29 } 30 31 int main () 32 { 33 int start = clock(); 34 mmap_analyse(); 35 printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC); 36 return 0; 37 }
達到0.49s,與原文不符(原文中使用mmnp耗時更短,在我的測試中,耗時變長了),可能是代碼與原作者的不一樣,原作者只給出一部分代碼,而測試需要寫出完整的代碼,可能我寫的代碼有問題。
以上測試結果在騰訊雲上進行,因為原作者當時的硬件條件可能比不上我所使用的環境,我在樹莓派 3B和我自己的電腦上測試了一下,所有平台硬件信息如下:
| 平台/硬件和軟件信息 | Cent OS | Raspberry | Windows |
| CPU | 1 Core | Broadcom BCM2837 1.2GHz | intel Core 5200u 2.2GHz |
| RAM | 1GB | 1GB | 12GB |
| Gcc | 4.8.5 | 4.9.2 | 5.3.0 |
PS: 這里忽略了硬盤的性能,理論上來說,硬盤的性能肯定能影響讀寫速度,只是沒有較好的方法比較三個平台的硬盤性能,只能作罷。不過在下面的表中我對比了我自己電腦上在Windows環境下和Linux環境下的情況。相較於原文,舍去VS的比較信息,全部使用了GNU/GCC.
測試結果如下
| 方法/平台/耗時(s) | Cent OS | Raspberry | Windows(本機) | Ubuntu(本機) |
| scanf | 1.180 | 14.786 | 4.488 | 1.158 |
| cin | 13.026 | 61.255 | 13.026 | 4.309 |
| cin(取消同步) | 1.240 | 7.694 | 8086 | 1.135 |
| fread | 0.37 | 3.503 | 0.327 | 0.284 |
| read | 0.31 | 2.975 | 0.370 | 0.285 |
| mmap | 0.49 | 5.945 | NULL | 0.447 |
在同等硬件條件下,Windows比Linux慢得多,在同等環境下,硬件好的自然快,樹莓派充分證明了這一點。
