对于scanf和cin的输入输出速度的验证

本文通过一系列实验对比了不同文件读取方法在多种环境下的性能表现,包括scanf、cin、fread、read及mmap等,并分析了各种方法的优劣。

本文为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还是短得多。
然后取消cinstdin之间的同步之后,代码如下:

 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 OSRaspberryWindows
CPU1 CoreBroadcom BCM2837 1.2GHzintel Core 5200u 2.2GHz
RAM1GB1GB12GB
Gcc4.8.54.9.25.3.0

PS: 这里忽略了硬盘的性能,理论上来说,硬盘的性能肯定能影响读写速度,只是没有较好的方法比较三个平台的硬盘性能,只能作罢。不过在下面的表中我对比了我自己电脑上在Windows环境下和Linux环境下的情况。相较于原文,舍去VS的比较信息,全部使用了GNU/GCC.

测试结果如下

方法/平台/耗时(s)Cent OSRaspberryWindows(本机)Ubuntu(本机)
scanf1.18014.7864.4881.158
cin13.02661.25513.0264.309
cin(取消同步)1.2407.69480861.135
fread0.373.5030.3270.284
read0.312.9750.3700.285
mmap0.495.945NULL0.447

在同等硬件条件下,Windows比Linux慢得多,在同等环境下,硬件好的自然快,树莓派充分证明了这一点。

转载于:https://www.cnblogs.com/hushuangpu/p/6661464.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值