本文为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慢得多,在同等环境下,硬件好的自然快,树莓派充分证明了这一点。