mmap执行不同的文件大小

时间:2016-10-26 21:30:53

标签: c file mmap

我正在使用mmap来读取文件。现在,当文件大小约为880 MB时,需要大约0.5秒来迭代文件。

现在我通过复制文件内容将文件大小增加了10倍。现在再次使用mmap需要大约1分钟。

我认为迭代的时间应该随文件大小线性增加。

这是简单的测试代码

FILE *fp = fopen64("filename", "rm");
if (fp == NULL)
{
    perror(NULL);
}
struct stat st;
fstat(fileno(fp), &st);
off_t fileSize = st.st_size;
char *data = (char *)mmap64(NULL, fileSize, PROT_READ,MAP_PRIVATE,fileno(fp), 0);
off_t ptr =0;
char c =(char)0;
while(ptr < fileSize) { c += data[ptr++] ;}
std::cout << c << "\n";

以下是结果。

对于fileSize 880MB

real    0m0.501s
user    0m0.447s
sys     0m0.053s

对于fileSize 8.8 GB

real    0m57.685s
user    0m10.773s
sys     0m3.690s

1 个答案:

答案 0 :(得分:3)

访问时间不是常数,数据集越大,访问时间就越慢。我建议阅读Latency Numbers Every Programmer Should Know

如果运行基准测试并调整数据集大小,您将看到性能发生变化的几个范围。

  1. 当数据集适合L1缓存时,性能最快。 L1缓存很小,比如每个内核64 KiB,但速度很快(约1个周期的访问时间,几乎和寄存器一样快)。

  2. 当您需要L2缓存时,性能会突然下降。 L2缓存比L1缓存更大,更慢。性能下降大概是10倍左右。

  3. 当数据集对于L2缓存而言太大但适合RAM时,性能会再次下降。缓存未命中的性能下降了10倍左右。

  4. 当数据集对于RAM而言太大但适合磁盘时,性能会下降。假设你有一个快速的SSD,性能命中率就像1000倍的缓存未命中,如果你有一个非SSD硬盘驱动器,可能会达到100,000倍。

  5. 您的880 MB数据集整齐地适合8 GiB的RAM,但是8,800 MB的数据集却没有,它们不能同时驻留。随机访问模式有点过分,但即使使用线性访问模式,您的页面也会从缓存中逐出,内核必须一遍又一遍地从磁盘中读取它们。

    很高兴假装你拥有无限量的存储空间,但存储速度相同,但这种情况甚至都不是真的。

    红鲱鱼

    • 实际上,将文件放入内存的唯一两种方法是使用readmmap。其他选项只是这两个选项之上的层。对于不在页面缓存中的数据的顺序访问,readmmap之间的差异无关紧要,请参阅mmap() vs. reading blocks

    • 访问模式将改变数据集变大时性能下降的程度,但它不会改变这样一个事实,即数据集太大而无法驻留不能比磁盘快。

    次要说明

    • 如果您要转到mmap然后使用open而不是fopen,则fopen是不必要的。

    • "m"的{​​{1}}标记不符合您的想法,此处没有用处。

    • 请勿使用fopenopen64fopen64或任何废话。只需使用mmap64即可。这是现代的做事方式,当然,它只与32位系统相关 - 而且由于您在零偏移处使用#define _FILE_OFFSET_BITS 64,所以没有点。

    • 致电mmap但是继续是错误的。 perror功能并非普遍可用,但可以满足您的需求。

    • 没有充分的理由不在这里使用err(),但它不会改变任何内容。

    以下是更一致的错误检查代码的外观:

    MAP_SHARED