Memory management mmap vs malloc vs calloc性能微基准:期待什么

Memory management mmap vs malloc vs calloc性能微基准:期待什么,memory-management,malloc,mmap,copy-on-write,Memory Management,Malloc,Mmap,Copy On Write,我创建了一个微基准来比较malloc和mmap的分配性能和RSS使用情况 我的结论是mmap是最快的,除非你真的使用内存。因此,我可能会将其用于人口稀少的数据结构 我的问题是这个结论是否正确,我得出的数字是否有意义(详情见下文) #包括 #包括 #包括 #包括 #包括 int main() { #定义大小100 无效*已分配[大小]; 大小[大小]; 当时,现在; memset(已分配,0,sizeof已分配); gettimeofday(&then,NULL); 大小\u t计数=0; 尺寸i

我创建了一个微基准来比较malloc和mmap的分配性能和RSS使用情况

我的结论是mmap是最快的,除非你真的使用内存。因此,我可能会将其用于人口稀少的数据结构

我的问题是这个结论是否正确,我得出的数字是否有意义(详情见下文)

#包括
#包括
#包括
#包括
#包括
int main()
{
#定义大小100
无效*已分配[大小];
大小[大小];
当时,现在;
memset(已分配,0,sizeof已分配);
gettimeofday(&then,NULL);
大小\u t计数=0;
尺寸i=0;
对于(;;)
{
如果(已分配[i])
{
munmap(分配[i],大小[i]);
//自由(分配[i]);
}
大小[i]=rand()%40000000+4096;
已分配[i]=
mmap(空,大小[i],
保护读,保护写,
MAP|u PRIVATE | MAP|u ANONYMOUS
/*|地图|*/
, -1, 0 );
//分配的[i]=malloc(大小[i]);
//分配的[i]=calloc(1,大小[i]);
//分配的[i]=calloc(大小[i],1);
i=(i+1)%SIZE;
如果(!(++count&0xfff))
{
gettimeofday(&now,NULL);
double timedelta=now.tv_sec-then.tv_sec+1.e-6*(now.tv_usec-then.tv_usec);
printf(“%f分配/s\n”,计数/timedelta);
}
}
}
在我的系统(sandy bridge台式机)上,我得到:

  • mmap:~900000次分配/秒,RSS~0.5MB,VSIZE~2GB
  • mmap+MAP_填充:~800分配/秒,RSS和VSIZE~2GB
  • malloc:~280.000分配/秒,RSS和VSIZE~2GB
  • calloc:~550分配/秒,RSS和VSIZE~2GB
  • malloc,malloc\u扰动=1:~260分配/秒,RSS和VSIZE~2GB
  • 我已经“记录”了这一点

    mmap+MAP_POPULATE大部分时间都在清除页面(200万次呼叫/秒)中,从uuu mm_POPULATE调用。我猜这将是我必须支付的页面错误税,如果代码实际使用mmap的内存,但是

    …malloc(没有malloc_摄动______________________________________________

    calloc和malloc与malloc_扰动_将其所有时间都花费在memset中。我理解马洛克。我认为calloc应该将所有页面映射到写页上所有零的副本,但是我的glibc显然没有这样做


    除了普通mmap之外,其他人都增加了RSS,这让我有点惊讶。我认为malloc和/或calloc只在使用内存时才会这样做。

    分配随机大小的缓冲区是不现实的。程序具有特有的访问模式,如果您想知道程序将如何执行,则需要模拟其访问模式。如果您只想知道
    malloc
    mmap
    的速度有多快,那么请针对各种固定的分配大小运行此基准测试。@Larsman的观点很好。将mmap更改为使用固定的分配大小不会改变我的系统上的任何内容,但malloc的行为非常不同。malloc'ing 40MB缓冲区的大小仍然为280.000 allocs/s,但没有增长的RSS。malloc'ing 4096字节缓冲区可达到约33.000.000 allocs/s,并且在malloc_扰动_情况下仍能达到4.000.000 allocs/s。这两种方法都比mmap/mmap+MAP更有趣。至少在Linux系统上,
    malloc
    'ing几十兆字节实际上会导致调用
    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 );
        }
      }
    }