读取二进制文件,Linux Buffer Cache

时间:2009-08-10 13:15:42

标签: c++ linux io

我正忙着写一些东西来测试Linux上磁盘IO的读取速度。

目前我有这样的东西来阅读文件:

编辑将代码更改为:

  const int segsize = 1048576;
  char buffer[segsize];
  ifstream file;
  file.open(sFile.c_str());
  while(file.readsome(buffer,segsize)) {}

对于150GB的foo.dat,我第一次读它时,大约需要2分钟。 但是如果我在第一次运行的60秒内运行它,那么运行大约需要3秒钟。怎么可能?当然,唯一可以快速读取的地方是RAM中的缓冲区缓存,文件太大而无法容纳在RAM中。

该机器有50GB的RAM,驱动器是NFS安装,具有所有默认设置。请告诉我在哪里可以确认此文件是否以此速度实际读取?我的代码错了吗?第一次读取文件时似乎需要一段正确的时间。

编辑添加: 发现我的文件只是随机读取。我已经设法通过将segsize从1048576更改为1024来解决这个问题。我不知道为什么更改这个允许ifstream读取整个文件而不是在随机点停止。

感谢您的回答。

5 个答案:

答案 0 :(得分:4)

在Linux上,您可以进行快速吞吐量测试:

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.863904 s, 243 MB/s

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.0748273 s, 2.8 GB/s

$ sync && echo 3 > /proc/sys/vm/drop_caches

$ dd if=/dev/md0 of=/dev/null bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.919688 s, 228 MB/s

echo 3 > /proc/sys/vm/drop_caches将正确刷新缓存

答案 1 :(得分:3)

  • in_avail不给出文件的长度,而是给出可用内容的下限(特别是如果已经使用了缓冲区,它将返回缓冲区中可用的大小)。它的目标是知道什么可以不被阻塞地阅读。

  • unsigned int很可能无法保存超过4GB的长度,因此读取的内容很可能在缓存中。

  • 如果您使用大文件,
  • C++0x Stream Positioning可能会让您感兴趣

答案 2 :(得分:1)

in_avail返回流读取缓冲区中可读取的内容的下限,而不是文件的大小。要通过流读取整个文件,请保持 调用流的readsome()方法并检查用gcount()方法读取了多少 - 当返回零时,你已经读取了everthing。

答案 3 :(得分:1)

  

第一次读取文件时似乎需要一段正确的时间。

在第一次阅读时,你在大约2分钟内阅读150GB。这大约是每秒10千兆比特。这是你期望的(基于网络到你的NFS挂载)?

答案 4 :(得分:1)

一种可能性是文件可能至少部分稀疏。稀疏文件具有真正空的区域 - 它们甚至没有分配给它们的磁盘空间。这些稀疏区域也不会消耗太多的缓存空间,因此读取稀疏区域基本上只需要时间来将它们被读入的用户空间页面清零。

您可以查看ls -lsh。第一列将是磁盘大小 - 如果它小于文件大小,则文件确实稀疏。要解压缩文件,只需写入它的每一页。

如果您想测试真正的磁盘速度,可以选择使用O_DIRECT标志open(2)来绕过缓存。请注意,使用O_DIRECT的所有IO必须是页对齐的,并且某些文件系统不支持它(特别是,它不能通过NFS工作)。此外,对于除基准测试之外的任何事情,这都是一个坏主意。看看Linus在this thread中的一些咆哮。

最后,要将所有缓存放在linux系统上进行测试,你可以这样做:

echo 3 > /proc/sys/vm/drop_caches

如果在客户端和服务器上执行此操作,则会强制文件内存不足。当然,这会对当时正在运行的任何其他内容产生负面的性能影响。