为什么移动缓冲区指针会减慢fread(C编程语言)?

时间:2014-02-26 10:27:51

标签: c buffer fread

我正在使用C中的 fread 读取1 GB文件。我正在使用以下循环以1MB块读取文件:

FILE *fp;
fp = fopen(filename, "rb");

unsigned char* buf;
buf = malloc(CHUNK_SIZE);

for(i = 0; i < NUMBER_OF_CHUNKS; ++i)
{
    fread(buf, CHUNK_SIZE, 1, fp);        

    //Do something with contents of buffer    
}
fclose(fp);

以这种方式读取文件大约需要2秒钟。

但是,我决定我想为整个文件的内容分配一个大缓冲区,并在每次迭代时在 fread 函数内“移动缓冲区指针”,如下所示:

FILE *fp;
fp = fopen(filename, "rb");

unsigned char* buf;
buf = malloc(CHUNK_SIZE * NUMBER_OF_CHUNKS);

for(i = 0; i < NUMBER_OF_CHUNKS; ++i)
{
    fread(&buf[i*CHUNK_SIZE], CHUNK_SIZE, 1, fp);         
}
fclose(fp);

这显着减慢了读数,现在大约需要40秒。

我的问题是:

  1. 为什么这会对性能产生如此巨大的影响?
  2. 如果我想以第二种方式阅读文件,你会建议我做什么,但我想保持时间不长?
  3. 该文件由一行字母数字字符组成。

    我想以第二种方式阅读它,以便我可以让其他线程访问已经读取的缓冲区中的块,而读取线程继续填充缓冲区的其余部分。

    谢谢!

2 个答案:

答案 0 :(得分:1)

您的计算机可能内存不足。一个千兆字节需要分配很多内存。你的操作系统我必须将一些数据交换到磁盘,这将导致一个数量级的减速。

您可以考虑单独分配每个块,并在完成后释放它们。这样,程序的总内存使用量受工作集的限制,而不是整个文件。

答案 1 :(得分:0)

当内存不足并且操作系统在交换分区中来回切换时,您不仅会导致大约3倍的磁盘流量。此外,对于机械/旋转硬盘[是的,那些仍然非常普遍],头部需要来回寻找交换空间和正在阅读的文件 - 即使文件没有碎片。这很可能会造成10-15倍的额外速度惩罚。

可能的解决方法是使用mmap将内存映射为连续内存,允许操作系统决定最佳交换策略。