本文为https://www.byvoid.com/zhs/blog/fast-readfile的验证性文章

---------------------------------------------------------------------------

首先生成一千万个随机数

 #include<cstdio>
#include<ctime>
#include<cstdlib>
int main ()
{
freopen("data.txt","w",stdout);
srand(time());
for(int i=;i<;i++)
printf("%d ",rand());
return ;
}

我用重定向把数据导出到"data.txt"了。

然后,用scanf来读取数据,并计时

 #include<cstdio>
#include<ctime>
int a[];
int main ()
{
int start = clock();
freopen("data.txt","r",stdin);
for(int i=;i<;i++)
scanf("%d",&a[i]);
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
}

执行之后,使用时间为1.18s,相比于原文的2.01秒,缩短了一截,然后测试一下使用cin输入的情况,代码如下:

 #include<cstdio>
#include<ctime>
#include<iostream>
int a[];
int main ()
{
int start = clock();
freopen("data.txt","r",stdin);
for(int i=;i<;i++)
std::cin>>a[i];
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
}

cin的使用时间为4.67s,比scanf更长,但是相比于原文的6.38s还是短得多。
然后取消cinstdin之间的同步之后,代码如下:

 #include<cstdio>
#include<ctime>
#include<iostream>
int a[];
int main ()
{
int start = clock();
std::ios::sync_with_stdio(false);
freopen("data.txt","r",stdin);
for(int i=;i<;i++)
std::cin>>a[i];
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
}

时间大幅缩短,为1.24s,与scanf很接近了。
然后按原文测试读入整个文件,代码如下:

 #include<iostream>
#include<ctime>
#include<cstdio>
const int MAXN = ;
const int MAXS = **;
int numbers[MAXN];
char buf[MAXS]; void analyse(char *buf, int len =MAXS)
{
int i;
numbers[i=]=;
for(char *p=buf;*p && p-buf<len;p++)
if(*p == ' ')
numbers[++i]=;
else
numbers[i]=numbers[i]*+*p-'';
} void fread_analyse()
{
freopen("data.txt","rb",stdin);
int len = fread(buf,,MAXS,stdin);
buf[len]='\0';
analyse(buf,len);
} int main ()
{
int start = clock();
fread_analyse();
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
return ;
}

时间如原文一般,大幅缩短,我这里测试得到0.37s,使用read测试,代码如下:

#include<iostream>
#include<ctime>
#include<cstdio>
#include<unistd.h>
#include<fcntl.h>
const int MAXN = ;
const int MAXS = **;
int numbers[MAXN];
char buf[MAXS]; void analyse(char *buf, int len =MAXS)
{
int i;
numbers[i=]=;
for(char *p=buf;*p && p-buf<len;p++)
if(*p == ' ')
numbers[++i]=;
else
numbers[i]=numbers[i]*+*p-'';
} 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.31s,有所进步,不过不是非常明显。
调用mmap,代码如下:

 #include<iostream>
#include<ctime>
#include<cstdio>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
const int MAXN = ;
const int MAXS = **;
int numbers[MAXN];
char buf[MAXS]; void analyse(char *buf, int len =MAXS)
{
int i;
numbers[i=]=;
for(char *p=buf;*p && p-buf<len;p++)
if(*p == ' ')
numbers[++i]=;
else
numbers[i]=numbers[i]*+*p-'';
} void mmap_analyse()
{
int fd = open("data.txt",O_RDONLY);
int len = lseek(fd,,SEEK_END);
char *mbuf = (char *) mmap(NULL,len,PROT_READ,MAP_PRIVATE,fd,);
analyse(mbuf,len);
} int main ()
{
int start = clock();
mmap_analyse();
printf("%.3lf\n",double(clock()-start)/CLOCKS_PER_SEC);
return ;
}

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

对于scanf和cin的输入输出速度的验证的更多相关文章

  1. scanf和cin的差异

    scanf和cin的差异 引例:http://www.cnblogs.com/shenben/p/5516996.html 大家都知道,在C++中有两种输入.输出方式—scanf和cin,但是,它们之 ...

  2. 关于scanf与cin哪个快的问题

    一开始入c++的时候成天跑cin,cout 直到有一天用cin,cout超时 才知道scanf比cin快的多 但是后来又听说加了ios::sync_with_stdio(false);的cin跟飞一样 ...

  3. 关于scanf 与 cin gets(),getline()......输入输出字符串的区别

    很对人对于字符串的输入输出一直是比较模糊的,今天总结一下几个常用的输入流符号对于输入字符串时的区别: 1.scanf(),首先 它遇到空格或回车键(\n)就会结束,并且会将回车符算入字符串中: 2.c ...

  4. c++使用cin、cout与c中使用scanf、printf进行输入输出的效率问题

    在c++中,我们使用cin和cout进行输入输出会比用scanf和printf更加简洁和方便,但是当程序有大量IO的时候,使用cin和cout进行输入输出会比用scanf和printf更加耗时, 在数 ...

  5. mac 下 sublime text 运行c++/c 不能使用scanf/cin

    { "cmd": ["g++", "${file}", "-o", "${file_path}/${file_ ...

  6. scanf 和cin 的区别

    笔试的时候经常遇到突然string s;cin>>s; 有的时候编译会错误,不知道为什么. 今天在练习枚举类型的时候,也遇到这样一个问题. enum weekday{Monday,Tues ...

  7. scanf 与 cin 的区别

    在论坛上看到有人提出一个如下的问题,在此总结一下. 原问题: http://topic.csdn.net/u/20110414/22/90d0606c-9876-48e4-9b69-bd8bd8a41 ...

  8. cin 和scanf,scanf比cin快很多

    //#include <iostream> #include <stdio.h> //#include <fstream> //using namespace st ...

  9. scanf和cin性能的比较

    我的实验机器配置是: 处理器:Intel(R) Core(TM) i3-7100U CPU @ 2.40GHz 2.40GHz 随机访问存储器:4.00GB 操作系统:Windows10 集成开发环境 ...

随机推荐

  1. BZOJ1857 [Scoi2010]传送带 【三分法】

    题目链接 BZOJ1857 题解 画画图就发现实际上是在\(AB\)上和\(CD\)上分别选两个点\(E\),\(F\),使得\(t_{AE} + t_{EF} + t_{FD}\)最小 然后猜想到当 ...

  2. 【bzoj2141】排队 [国家集训队2011]排队(魏铭) 树套树 线段树套替罪羊树

    这个题就是动态偏序对,每次操作做两个删除两个插入就好了. #include<cstdio> #include<iostream> #include<cstring> ...

  3. git使用笔记(六)github

    By francis_hao    Nov 20,2016 github介绍 github是一个网站https://github.com/,可以实现基于git(当然,svn也是可以的)的代码托管工作. ...

  4. Math.abs为Integer.Min_VALUE返回错误的值

      Math.abs为Integer.Min_VALUE返回错误的值 这段代码: System.out.println(Math.abs(Integer.MIN_VALUE)); 回报-2147483 ...

  5. VC遍历窗体控件的实现

    最近在写控制台,在设计界面按钮风格时不想通过每个按钮的ID来获取其句柄,而是通过遍历窗体所有控件,然后判断其控件类型进而来实现. 代码如下: // 遍历得到页面中的所有Button控件,依次设定其样式 ...

  6. java消息中间件入门

    消息中间件来解耦服务调用 比如1个登录系统,登录的话需要调用很多系统的其他服务,如果中间调用失败,可能会导致登录信息一致无法返回,同时也增加了系统的耦合度.而用消息中间件的话,则是不发送服务到其他系统 ...

  7. 动态规划:划分DP

    划分型动态规划之数的划分 先贴上2014年10月31日的那份代码,甚至怀念当时在机房YY这道题的场面 高中最快乐的时候.. #include<iostream> using namespa ...

  8. 【uva11732-"strcmp()" Anyone?】Trie

    http://acm.hust.edu.cn/vjudge/problem/28438 题意:给定n个字符串,问用strcmp函数比较这些字符串共用多少次比较. 题解: 插入一个‘#’作为字符串的结束 ...

  9. cve-2012-5613 mysql本地提权

    cve-2012-5613  是一个通过FILE权限写Trigger的TRG存储文件(即伪造Trigger),由root触发而导致权限提升的漏洞.不知道为什么这个漏洞一直没修,可能mysql认为这是一 ...

  10. MySQL MyISAM优化设置点滴

    先说一点问题:   Mysql中的InnoDB和MyISAM是在使用MySQL中最常用的两个表类型,各有优缺点.两种类型最主要的差别就是 InnoDB 支持事务处理与外键和行级锁.而MyISAM不支持 ...