malloc和mmap性能对比

5
我对使用malloc分配的内存和使用mmap映射文件(由磁盘上的文件支持)进行写入1.28亿个整数的性能测试...我本以为结果会有些相似,因为我理解当向映射文件写入数据时,数据最初被写入内存并且pdflush在后台写入磁盘(可以配置频率)。使用malloc,写入1.28亿个整数需要0.55秒;而用mmap需要1.9秒。
所以我的问题是:为什么会有差异。我的初步想法是pdflush占用了总线或者当pdflush访问内存时,它会阻塞写入...但是,第二次运行mmap版本的结果为0.52秒(由于缓存),这让我相信每个mmap后面的页面只有在写入时才分配 (尽管通过调用mmap来保留它)...据我所知,malloc产生的内存直到第一次写入才实际分配...难道最初的差异是因为在malloc的初始写入后,整个块都被分配了,而使用mmap时,每次写入新页面时,操作系统必须先分配它吗?
更新:
操作系统: CentOS Linux release 7.0.1406 (Core) 内核:3.10.0-123.el7.x86_64 gcc:4.8.2
int* pint = malloc(128000000 * sizeof(int));
int* pint_copy = pint;

clock_t start = clock();

int i;
for(i = 0; i < 128000000; ++i)
{
    *pint++ = i;
}   

clock_t end = clock();

double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("%f\n", cpu_time_used);

free(pint_copy);

vs

int fd = open("db", O_RDWR | O_CREAT, 0666);
const size_t region_size = ((512000000 / sysconf(_SC_PAGE_SIZE)) + 1) * sysconf(_SC_PAGE_SIZE); 

int return_code = ftruncate(fd, region_size);

if (return_code < 0)
    printf("mapped memory file could not be truncated: %u\n", return_code);

int* pint = mmap(NULL, region_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
int* pint_copy = pint;
close(fd);  

clock_t start = clock();

int i;
for(i = 0; i < 128000000; ++i)
{
    *pint++ = i;
}   

clock_t end = clock();

double cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("%f\n", cpu_time_used);

fgetc(stdin);

munmap(pint_copy, region_size);

添加:

int z = 512;
while(z < 128000000)
{
    pint[z] = 0;

    z += 1024;
}

AFTER:

  clock_t start = clock();     

在两次试验中均产生了0.37秒的时间,这使我相信“触碰”每个页面会导致操作系统分配物理内存(无论是用于mmap还是malloc)...这也部分是因为“触碰”页面将一些内存移动到缓存中...有人知道在长时间大量写内存时,pdflush是否会阻塞或减慢内存写入速度吗?


2
这非常依赖于操作系统(和编译器),但你没有说明你正在使用哪个。 - Hogan
2
Malloc 很可能在内部也使用 mmap,可以通过 strace 进行检查。它很可能正在映射共享内存对象(请参见 shm_open,在最近的 Linux 中,这会在 /dev/shm 中打开一个文件,并使用 tmpfs)。此外,mmap 中的 MMAP_POPULATE 标志可能也与此有关。 - Nick Zavaritsky
2
有很多变量可能会影响这个问题 - 其他正在运行的程序、CPU数量、内存可用性、中断、后台I/O、预读和/或预取模式、实际的mmap()使用情况(即是否映射了/dev/zero或真实文件或其他内容,如果是真实文件,它是否事先存在或需要分配),等等... - twalberg
1
相关链接:https://dev59.com/7XE85IYBdhLWcg3wnU6p,https://dev59.com/GIfca4cB1Zd3GeqPdAAi - Thomas Padron-McCarthy
2个回答

1

是的,你说得对。使用mmap获得的页面在访问之前不会被填充。你不能保证这一点,但通常操作系统使用写回(这没有任何惩罚,只有收益)和需求分页(必须支付第一次访问)。


1
我不知道答案,但这看起来像是你在比较苹果和橙子。一方面,你正在写入(malloc'd)内存,而另一方面,你同时正在写入内存和(mmap'd)磁盘。我预计第二个操作会比第一个慢一个数量级,因为它涉及设备I/O活动,而第一个操作没有任何I/O。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接