为什么切片分配器比glib2.0中的malloc慢?

时间:2015-02-09 09:23:10

标签: c glib

我写了两个简单的程序来比较 g_slice_alloc() g_malloc()的速度。

g_slice_alloc()版本:

#include <gtk/gtk.h>


int main(int argc, char *argv[])
{
    gchar *mem[1000000];
    gint i;
    for(i=0;i<1000000;i++){
        mem[i]=g_slice_alloc(50);
    }
    for(i=0;i<1000000;i++){
       g_slice_free1(50,mem[i]);
    }
    return 0;
}

g_malloc()版本

#include <gtk/gtk.h>


int main(int argc, char *argv[])
{
    gchar *mem[1000000];
    gint i;
    for(i=0;i<1000000;i++){
        mem[i]=g_malloc(50);
    }
    for(i=0;i<1000000;i++){
         g_free(mem[i]);
    }
    return 0;
}

编译它们

gcc slice.c -o slice `pkg-config --libs --cflags gtk+-3.0`
gcc malloc.c -o malloc `pkg-config --libs --cflags gtk+-3.0`

并测试它们

$ time ./slice

real    0m0.091s
user    0m0.063s
sys 0m0.025s

$ time ./malloc

real    0m0.071s
user    0m0.050s
sys 0m0.021s
g_slice_alloc()版本预计运行得更快,但实际上并非如此。为什么它更慢?

这是一个很好的测试案例吗?

我尝试了另一种测试速度的方法。

#include <gtk/gtk.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    gchar *mem[1000000];
    gint i;
    for(i=0;i<1000000;i++){
        gint j=i>10000?10000:i;
        mem[i]=g_slice_alloc(j);
    }
    for(i=0;i<1000000;i++){
       gint j=i>10000?10000:i;
       g_slice_free1(j,mem[i]);
    }
   return 0;
}

#include <gtk/gtk.h>  
#include <stdlib.h>

int main(int argc, char *argv[])
{
    gchar *mem[1000000];
    gint i;
    for(i=0;i<1000000;i++){
         gint j=i>10000?10000:i;
        mem[i]=g_malloc(j);
    }
    for(i=0;i<1000000;i++){
        gint j=i>10000?10000:i;
        g_free(mem[i]);
    }
    return 0;
 }

这次他们非常接近,有时 g_slice_alloc()更快,而somtime g_malloc()更快。

$ time ./malloc

real    0m1.515s
user    0m0.285s
sys 0m1.229s

$ time ./slice

real    0m1.521s
user    0m0.278s
sys 0m1.215s

但是这个测试不能证明 g_slice_alloc()更快,它只是告诉 g_slice_alloc() g_malloc()

1 个答案:

答案 0 :(得分:4)

自从添加glibc以来,

GSlice的malloc已经改进了很多(当glibc的malloc非常慢时)。 GSlice曾经比malloc快得多,但是由于malloc中的积极优化,现在它更快,特别是对于线程较多的应用程序。与此同时,GSlice自添加以来并没有真正发生重大变化。

AFAIK,现在使用GSlice的唯一真正原因是它在不同平台上更加稳定(例如,显然Windows'momooc对于GStreamer来说太慢了。)

所有这一切,你所拥有的并不是一个好的考验。像GSlice这样的slab风格的分配器传统上擅长的是减少内存碎片,这是由大量不同大小的分配/释放混合在一起造成的。你拥有的是一堆分配,随后是一堆免费。

此外,像GSlice这样的分配器依赖于相同大小的分配,因此增加分配大小的测试部分不能很好地工作 - GSlice用于对象,而不是字符串和缓冲区。