在编写缓存的过程中,经常会遇到以下问题:是事先分配一段足够的大内存好,还是临时增加的好呢?我们一般认为事先分配足够大的内存是用空间换时间,以换取更高的性能,临时增加内存容量是用时间换空间,以换取内存更高的利用率,本篇对比测试的目的主要是测试看看两种的性能差距的具体量值。
第二部分是直接申请一个大内存块;
第三部分和第一部分意思相同,只不过用效率更高的realloc来实现。
1、经过对比测试发现,第一部分的代码效率最低,现在我们只分析第二部分和第三部分代码
当realloc中的size大小增加不多时(nsize+1024*1024*n,n<32),即使触发了realloc新建内存时,第三部分代码的效率无论在资源利用率和时间都占优;但当新增内存过大的n>32时,第二部分和第三部分的结果不分仲伯,同在一个数据量级,耗时相差时上时下。
2、对上次结果经过分析,memset耗时比较大,初始化大内存时可能比较耗时,现在注释memset,经过测试对比发现若realloc未触发新建内存时第三部分代码的效率无论在资源利用率和时间都占优,当需要的增加内存增大时,迫使realloc新建内存时(发生内存copy,消耗等操作),则第二部分耗时占优。
结论:memset初始化内存耗时较多,对性能有严格的要求,可不用memset初始化内存,但要严格控制内存的边界问题。
如果申请使用内存大小在0~2*size之间,若预判大部分情况下可能使用在小于size或在size上下时,可初始化内存块为size,使用realloc来扩展少部分内存时,效率比较高,当无法预判则可使用malloc来申请一个大内存,但不要初始化,否则耗时比按需增加要高。
下面是本次测试的代码:
void testmalloc()
{
long long nsize=64*1024*1024;
//第一部分
time_t begint=GetTickCount();
char* p1=(char*)malloc(nsize);
memset(p1,0,nsize);
long long double_nsize=nsize*2;
char* p2=(char*)malloc(double_nsize);
memset(p2,0,double_nsize);
memcpy(p2,p1,nsize);
free(p1);
time_t endint=GetTickCount();
printf("new malloc time is %d\n",endint-begint);
free(p2);
//第二部分
begint=GetTickCount();
char* p3=(char*)malloc(double_nsize);
memset(p3,0,double_nsize);
endint=GetTickCount();
printf("big malloc time is %d\n",endint-begint);
free(p3);
//第三部分
begint=GetTickCount();
char* p5=NULL;
char* p4=(char*)malloc(nsize);
memset(p4,1,nsize);
if (double_nsize>nsize)
{
//p5=(char*)realloc(p4,double_nsize);
p5=(char*)realloc(p4,nsize+1024*3);
if (!p5)
{
return;
}
}
endint=GetTickCount();
printf("befor %p,after %p,realloc time is %d\n",p4,p5,endint-begint);
free(p5);
}
第一部分模拟先分配的内存不够,再次增加内存的业务背景:先申请一个小内存块,在申请一个大内存块,将先前申请的内存块的内容copy到大内存块;
第二部分是直接申请一个大内存块;
第三部分和第一部分意思相同,只不过用效率更高的realloc来实现。
1、经过对比测试发现,第一部分的代码效率最低,现在我们只分析第二部分和第三部分代码
当realloc中的size大小增加不多时(nsize+1024*1024*n,n<32),即使触发了realloc新建内存时,第三部分代码的效率无论在资源利用率和时间都占优;但当新增内存过大的n>32时,第二部分和第三部分的结果不分仲伯,同在一个数据量级,耗时相差时上时下。
2、对上次结果经过分析,memset耗时比较大,初始化大内存时可能比较耗时,现在注释memset,经过测试对比发现若realloc未触发新建内存时第三部分代码的效率无论在资源利用率和时间都占优,当需要的增加内存增大时,迫使realloc新建内存时(发生内存copy,消耗等操作),则第二部分耗时占优。
结论:memset初始化内存耗时较多,对性能有严格的要求,可不用memset初始化内存,但要严格控制内存的边界问题。
如果申请使用内存大小在0~2*size之间,若预判大部分情况下可能使用在小于size或在size上下时,可初始化内存块为size,使用realloc来扩展少部分内存时,效率比较高,当无法预判则可使用malloc来申请一个大内存,但不要初始化,否则耗时比按需增加要高。