从fread和mmap谈C++读文件的性能

[来源] 达内    [编辑] 达内   [时间]2012-08-30

不管你的CPU有4个核还是8个核,主频有2G还是3G,硬盘IO速度总是有个上限的。

 在进行大规模数据处理时,读文件很有可能成为速度瓶颈。不管你的CPU有4个核还是8个核,主频有2G还是3G,硬盘IO速度总是有个上限的。在本人最近的一次经历中,对一个11G的文本进行数据处理,一共耗时34.8秒,其中竟然有30.2秒用在访问IO上,占了所有时间的87%左右。

  虽然说硬盘IO是有上限的,那么C++为我们提供的各函数,是否都能让我们达到这个上限呢?为了求得真相,我对这个11G的文本用fread函数读取,在linux下用iostat检查硬盘的访问速度,发现读的速度大约在380M/s。然后用dd指令测了一下读文本的访问速度,发现速度可以达到 460M/s。可见单线程fread访问并没有达到硬盘的读取上限。第一次考虑会不会是fread访问硬盘的时候有一些固定开销,用多线程可以达到流水访问IO的效果提高读文本的效率,结果发现多线程也只有380M/s的读取速率。

  为什么fread的效率达不到最大呢?查阅一些资料才知,用fread/fwrite方式访问硬盘,用户须向内核指定要读多少,内核再把得到的内容从内核缓冲池拷向用户空间;写也须要有一个大致如此的过程。这样在访问IO的时候就多经历了这么一个内核的buffer,造成速度的限制。一个解决的办法是mmap。mmap就是通过把文件的某一块内容直接映射到用户空间上,用户可以直接向内核缓冲池读写这一块内容,这样一来就少了内核与用户空间的来回拷贝所以通常更快。

  为了从数据说明这个问题,我引用一位网友的结论,希望对大家有所启发。

  方法/平台/时间(秒) Linux gcc Windows mingw Windows VC2008

  scanf 2.010 3.704 3.425

  cin 6.380 64.003 19.208

  cin取消同步 2.050 6.004 19.616

  fread 0.290 0.241 0.304

  read 0.290 0.398 不支持

  mmap 0.250 不支持 不支持

  Pascal read 2.160 4.668

  作者:jiang1st2010

资源下载