我创建了一个微基准来比较 malloc 与 mmap 的分配性能和 RSS 使用情况。
我得出的结论是 mmap 是最快的,除非您实际使用内存。因此,我可能可以将它用于人口稀少的数据结构。
我的问题是这个结论是否正确以及我得出的数字是否有意义(详见下文)。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/time.h>
int main()
{
#define SIZE 100
void* allocated[SIZE];
size_t size[SIZE];
timeval then, now;
memset(allocated, 0, sizeof allocated );
gettimeofday(&then, NULL);
size_t count = 0;
size_t i = 0;
for ( ;; )
{
if ( allocated[ i ] )
{
munmap( allocated[ i ], size[ i ] );
//free( allocated[ i ] );
}
size[ i ] = rand() % 40000000 + 4096;
allocated[ i ] =
mmap( NULL, size[ i ],
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS
/* | MAP_POPULATE */
, -1, 0 );
//allocated[ i ] = malloc( size[ i ] );
//allocated[ i ] = calloc( 1, size[ i ] );
//allocated[ i ] = calloc( size[ i ], 1 );
i = (i+1) % SIZE;
if ( !( ++count & 0xfff ) )
{
gettimeofday(&now, NULL);
double timedelta = now.tv_sec-then.tv_sec + 1.e-6*( now.tv_usec-then.tv_usec );
printf( "%f allocations/s\n", count/timedelta );
}
}
}
在我的系统(沙桥台式机)上,我得到:
- mmap:~900.000 分配/秒,RSS ~0.5 MB,VSIZE ~2GB
- mmap + MAP_POPULATE:~800 分配/秒,RSS 和 VSIZE ~2GB
- malloc:~280.000 分配/秒,RSS 和 VSIZE ~2GB
- calloc:~550 分配/秒,RSS 和 VSIZE ~2GB
- malloc, MALLOC_PERTURB_ == 1: ~260 allocations/s, RSS and VSIZE ~2GB
我已经“录制”了一点。
mmap + MAP_POPULATE 大部分时间都在 clear_page_c_e(2M 调用/秒)中,从 __mm_populate 调用。我猜这将是我必须支付的页面错误税,如果代码实际上对mmap'ed内存做了一些事情,但是......
...malloc(没有将 MALLOC_PERTURB_ 环境变量设置为任何内容)也将大部分时间花在 clear_page_c_e 中(也是 2M 调用/秒),但实现了更多的分配/秒。
带有 MALLOC_PERTURB_ 的 calloc 和 malloc 将所有时间都花在 memset 中。我理解malloc。我认为 calloc 应该将所有页面映射到一个全为零的写时复制页面,但我的 glibc 显然没有这样做。
除了普通的 mmap 之外,其他人都增加了 RSS,这让我有点惊讶。我认为 malloc 和/或 calloc 只会在使用内存时这样做。