当软件性能优化到一定程度之后,用vturn查看hotspots,将会发现malloc/delete会花费很高比例的时间,此时如果是多线程程序,频繁的lock将会是一个瓶颈,这里有一篇oracle的文章,很好的介绍了这样的情况http://www.oracle.com/technetwork/articles/servers-storage-dev/mem-alloc-1557798.html
在linux平台,此时我们主要考虑到两种优化方案,各自都有很细节的文章可以参考
1. google的MTMalloc (http://goog-perftools.sourceforge.net/doc/tcmalloc.html)
2. gnu的__mt_alloc (http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch32.html)
下面我做了一个简单的测试程序
改变的tune_type参数,发现gnu的最优的情况比malloc快一两倍,最糟糕的情况是反而比malloc慢十倍,很依赖具体的实现情况,另外tcmalloc使用很简单,我们只要改一下link的库,测试的结果是比不用tcmalloc有七八倍的性能提高,从结构上来讲gnu的在更高层次的代码上优化,想通过memory pool和thread id的比较来减少申请内存的次数和不同线程之间的竞争,它最终调用的还是malloc尤其是当申请的内存大于_M_max_bytes的时候就完全是调用malloc了,而TCMalloc是替换掉了系统的malloc,是更加底层的优化。
总结一下,gnu的使用麻烦,接口繁琐,还可能有负面效应,google的比gnu的速度快,使用也方便很多。
在linux平台,此时我们主要考虑到两种优化方案,各自都有很细节的文章可以参考
1. google的MTMalloc (http://goog-perftools.sourceforge.net/doc/tcmalloc.html)
2. gnu的__mt_alloc (http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch32.html)
下面我做了一个简单的测试程序
- // test app
- void* vectormemorycost(void*){
- cout << "malloc test"<< endl;
- int blocksize = 512;
- for(int j=0;j<20; ++j){
- int sum=25000;
- char* p1[sum];
- for(int i=0; i<sum;++i){
- p1[i]=(char*)malloc(blocksize);
- }
- for(int i=0; i<sum;++i){
- free(p1[i]);
- }
- }
- return 0;
- }
- void* mtallocateMemorycost(void*){
- cout << "mt alloc test"<< endl;
- typedef pod value_type;
- typedef __gnu_cxx::__mt_alloc<value_type> allocator_type;
- typedef __gnu_cxx::__pool_base::_Tune tune_type;
- ///_M_align(__align)
- ///_M_max_bytes(__maxb)
- ///_M_min_bin(__minbin),
- ///_M_chunk_size(__chunk)
- ///_M_max_threads(__maxthreads),
- ///_M_freelist_headroom(__headroom)
- ///_M_force_new(__force)
- tune_type t_our(16, 510, 32, 5120, 20, 10, false);
- allocator_type a;);
- a._M_set_options(t_our);
- int blocksize = 512;
- for(int j=0;j<20; ++j){
- int sum=25000;
- allocator_type::pointer p1[sum];
- for(int i=0; i<sum;++i){
- p1[i]=a.allocate(blocksize);
- }
- for(int i=0; i<sum;++i){
- a.deallocate(p1[i], blocksize);
- }
- }
- return 0;
- }
- typedef void*(*pFoo)(void*);
- void mtallocatePrivate(pFoo func){
- int i;
- int cores = 4;
- pthread_t threads[cores];
- /* Create threads to do the work. */
- for (i = 0; i < cores; ++i)
- // pthread_create (&(threads[i]), NULL, vectormemorycost, NULL);
- pthread_create (&(threads[i]), NULL, func, NULL);
- /* Wait for all threads to finish. */
- for (i = 0; i < cores; ++i)
- pthread_join (threads[i], NULL);
- }
- void mtallocate(){
- for(int i=0;i<5;++i){
- mtallocatePrivate(mtallocateMemorycost);
- mtallocatePrivate(vectormemorycost);
- }
- }
改变的tune_type参数,发现gnu的最优的情况比malloc快一两倍,最糟糕的情况是反而比malloc慢十倍,很依赖具体的实现情况,另外tcmalloc使用很简单,我们只要改一下link的库,测试的结果是比不用tcmalloc有七八倍的性能提高,从结构上来讲gnu的在更高层次的代码上优化,想通过memory pool和thread id的比较来减少申请内存的次数和不同线程之间的竞争,它最终调用的还是malloc尤其是当申请的内存大于_M_max_bytes的时候就完全是调用malloc了,而TCMalloc是替换掉了系统的malloc,是更加底层的优化。
总结一下,gnu的使用麻烦,接口繁琐,还可能有负面效应,google的比gnu的速度快,使用也方便很多。