免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 19441 | 回复: 24

[C] 内存分配,jemalloc/tcmalloc/glibc测评 [复制链接]

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2016-06-21 10:15 |显示全部楼层
本帖最后由 knull 于 2016-06-21 10:23 编辑

    最近在了解内存分配;了解了下jemalloc/tcmalloc——传说中的性能相对glibc内存分配大幅度提高的两个很火的内存分配器。
    但是,经过简单的性能测试代码测试,发现性能并没有比glibc好。
    难道是我测试方法有问题?请各位大侠赐教,探讨~~~

系统环境:CentOS7.1;512M;1CPU(单核);(VM虚拟机安装)
编译环境:gcc(g++)4.8.5;用的是g++ -g -O2进行编译;
测试环境:单线程,8k次malloc/free。分别测试glibc/tcmalloc/jemallc。对比平均耗时,是us(微妙)级别的。
详细说明:
        用内存分配器,一种可以直接调用jemalloc代码;还有一种可以设置环境变量LD_PRELOAD来替换glibc的malloc。
        1、我首先测试了直接调用的情况(仅测试了je和glibc):直接调用jemalloc。发现,jemalloc平均耗时至少是glibc的2倍,最高近3倍.
        2、设置环境变量,LD_PRELOAD.分别测试了je/tc/glibc。
                测试发现,该情况下,je比直接调用耗时减少50%。(这点出乎我的意料,想不通)
                je耗时比tc稍好。但是glibc比两者都要稍好(三者都相差不是特别大,不到10%)。
下面附上我的测试代码,请大家帮忙分析下啊~~~
  1. #include <list>
  2. #include <stdlib.h>
  3. #include <ctime>
  4. #include <jemalloc/jemalloc.h>
  5. #include <string>
  6. class TimeKeeper
  7. {
  8. public :
  9.     TimeKeeper(const char *name,int64_t &count):name_(name),counter_(count)
  10.     {
  11.         clock_gettime(CLOCK_MONOTONIC, &tp_start_);
  12.     }
  13.     ~TimeKeeper()
  14.     {
  15.         struct timespec tp_end;
  16.         clock_gettime(CLOCK_MONOTONIC, &tp_end);
  17.         //
  18.         int64_t cost = tp_end.tv_sec - tp_start_.tv_sec;
  19.         cost = (tp_end.tv_nsec-tp_start_.tv_nsec) + (cost*1000*1000*1000);
  20.         counter_ += cost;
  21.     }
  22. private :
  23.     struct timespec tp_start_;
  24.     int64_t &counter_;
  25.     std::string name_;
  26. };

  27. std::list<void*> buf;
  28. int32_t loop = 8*1024;
  29. int32_t MAX_MEM_SIZE = 128*1024;
  30. int64_t alloc_time_;
  31. int64_t free_time_;

  32. int32_t GetRand(int32_t n = 16)
  33. {
  34.     return rand()%n+1;
  35. }

  36. void *myalloc(size_t n)
  37. {
  38.         TimeKeeper tmp(__FUNCTION__,alloc_time_);
  39.         //return je_malloc(n);
  40.         return malloc(n);
  41. }

  42. void myfree(void *ptr)
  43. {
  44.         TimeKeeper tmp(__FUNCTION__,free_time_);
  45.         //je_free(ptr);
  46.         free(ptr);
  47. }

  48. void test_muli_times2()
  49. {
  50.     int32_t num = GetRand();
  51.     void *ptr = NULL;
  52.     for (int i=0; i< loop; ++i)
  53.     {
  54.         ptr = myalloc(GetRand(MAX_MEM_SIZE));
  55.         --num;
  56.         if (num == 0)
  57.         {
  58.             myfree(ptr);
  59.             num = GetRand();
  60.         }
  61.         else
  62.         {
  63.             buf.push_back(ptr);
  64.         }
  65.     }
  66.     while (!buf.empty())
  67.     {
  68.         ptr = buf.back();
  69.         buf.pop_back();
  70.         myfree(ptr);
  71.     }
  72.     printf("alloc %ld obj! cost %ld'ns! avg = %d!\n",loop,alloc_time_,alloc_time_/loop);
  73.     printf("freed %ld obj! cost %ld'ns! avg = %d!\n",loop,free_time_,free_time_/loop);
  74. }

  75. int main ()
  76. {
  77.   //TYPEPRINT(HashNode);
  78.   test_muli_times2();
  79.   return 0;
  80. }
复制代码

论坛徽章:
323
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
发表于 2016-06-21 10:39 |显示全部楼层
好像tcmalloc主要是提升了多线程的性能吧
另外测试性能最好不用虚拟机,里面那个list最好也去掉

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2016-06-21 10:44 |显示全部楼层
回复 2# hellioncu
谢谢你的回复;
我刚刚查看了下资料,发现一般说明都带多线程的;而且,重点说明也是“多核时代”。所以我又重新用多线程,4核测试下(仍然虚拟机),发现的确tc性能更好,je比glibc稍好

   

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2016-06-21 10:47 |显示全部楼层
本帖最后由 knull 于 2016-06-21 10:49 编辑

我刚刚查看了下资料,发现一般说明都带多线程的;而且,重点说明也是“多核时代”。
我又重新用4线程,4核测试下(仍然虚拟机)
je的malloc/free跟glibc的差不多(je稍好);
tc的malloc比glibc好很多,有4~5倍;但是free比glibc差很多,耗时接近glibc的2倍
下面是修改之后的代码(主要是增加多线程了):
  1. #include <list>
  2. #include <stdlib.h>
  3. #include <ctime>
  4. //#include <jemalloc/jemalloc.h>
  5. #include <string>
  6. #include <thread>
  7. #include <atomic>

  8. std::atomic<int64_t> alloc_time_;
  9. std::atomic<int64_t> free_time_;

  10. class TimeKeeper
  11. {
  12. public :
  13.     TimeKeeper(bool isalloc):alloc_(isalloc)
  14.     {
  15.         clock_gettime(CLOCK_MONOTONIC, &tp_start_);
  16.     }
  17.     ~TimeKeeper()
  18.     {
  19.         struct timespec tp_end;
  20.         clock_gettime(CLOCK_MONOTONIC, &tp_end);
  21.         //
  22.         int64_t cost = tp_end.tv_sec - tp_start_.tv_sec;
  23.         cost = (tp_end.tv_nsec-tp_start_.tv_nsec) + (cost*1000*1000*1000);
  24.         if (alloc_)
  25.                 {
  26.                         alloc_time_.fetch_add(cost);
  27.                 }
  28.                 else
  29.                 {
  30.                         free_time_.fetch_add(cost);
  31.                 }
  32.     }
  33. private :
  34.     struct timespec tp_start_;
  35.         bool alloc_;
  36. };


  37. int32_t loop = 8*1024;
  38. int32_t MAX_MEM_SIZE = 128*1024;

  39. int32_t GetRand(int32_t n = 16)
  40. {
  41.     return rand()%n+1;
  42. }

  43. void *myalloc(size_t n)
  44. {
  45.         TimeKeeper tmp(true);
  46.         //return je_malloc(n);
  47.         return malloc(n);
  48. }

  49. void myfree(void *ptr)
  50. {
  51.         TimeKeeper tmp(false);
  52.         //je_free(ptr);
  53.         free(ptr);
  54. }

  55. void test_muli_times2()
  56. {
  57.        
  58.         std::list<void*> buf;
  59.     int32_t num = GetRand();
  60.     void *ptr = NULL;
  61.     for (int i=0; i< loop; ++i)
  62.     {
  63.         ptr = myalloc(GetRand(MAX_MEM_SIZE));
  64.         --num;
  65.         if (num == 0)
  66.         {
  67.             myfree(ptr);
  68.             num = GetRand();
  69.         }
  70.         else
  71.         {
  72.             buf.push_back(ptr);
  73.         }
  74.     }
  75.     while (!buf.empty())
  76.     {
  77.         ptr = buf.back();
  78.         buf.pop_back();
  79.         myfree(ptr);
  80.     }

  81. }

  82. void test_threads()
  83. {
  84.         std::thread t1(test_muli_times2);
  85.         std::thread t2(test_muli_times2);
  86.         std::thread t3(test_muli_times2);
  87.         std::thread t4(test_muli_times2);
  88.         t1.join();
  89.         t2.join();
  90.         t3.join();
  91.         t4.join();
  92.         int64_t cost = alloc_time_.load();
  93.         int32_t times = loop * 4;
  94.     printf("alloc %ld obj! cost %ld'ns! avg = %d!\n",times,cost,cost/times);
  95.         cost = free_time_.load();
  96.     printf("freed %ld obj! cost %ld'ns! avg = %d!\n",times,cost,cost/times);
  97. }

  98. int main ()
  99. {
  100.   //TYPEPRINT(HashNode);
  101.   test_threads();
  102.   return 0;
  103. }
复制代码

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2016-06-21 11:10 |显示全部楼层
虚拟机多核没卵用的,特别是计算密集场景

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
发表于 2016-06-21 11:16 |显示全部楼层
lxyscls 发表于 2016-06-21 11:10
虚拟机多核没卵用的,特别是计算密集场景

虚拟机可以多核。你是哪个虚拟机?

论坛徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16赛季CBA联赛之江苏
日期:2017-11-27 11:42:3515-16赛季CBA联赛之八一
日期:2017-04-12 14:26:2815-16赛季CBA联赛之吉林
日期:2016-08-20 10:43:1215-16赛季CBA联赛之广夏
日期:2016-06-23 09:53:58程序设计版块每日发帖之星
日期:2016-02-11 06:20:00程序设计版块每日发帖之星
日期:2016-02-09 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-25 16:40:3515-16赛季CBA联赛之广夏
日期:2015-12-22 09:39:36程序设计版块每日发帖之星
日期:2015-08-24 06:20:002015亚冠之德黑兰石油
日期:2015-08-07 09:57:302015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2016-06-21 11:24 |显示全部楼层
回复 6# yulihua49


    vmware workstation

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2016-06-21 11:50 |显示全部楼层
回复 5# lxyscls
好的,谢谢回复;
我本地测试下试试;不过,多线程下的确有好转

   

论坛徽章:
2
技术图书徽章
日期:2014-04-15 16:30:27金牛座
日期:2014-06-06 16:20:49
发表于 2016-06-21 12:24 |显示全部楼层
回复 6# yulihua49

主机本身是I3的多核机器;虚拟机是VMware,可以设置核心数的
   

论坛徽章:
72
20周年集字徽章-20	
日期:2020-10-28 14:04:30操作系统版块每日发帖之星
日期:2016-07-13 06:20:0015-16赛季CBA联赛之广夏
日期:2016-07-10 09:04:02数据库技术版块每日发帖之星
日期:2016-07-09 06:20:00操作系统版块每日发帖之星
日期:2016-07-09 06:20:00数据库技术版块每日发帖之星
日期:2016-07-07 06:20:00操作系统版块每日发帖之星
日期:2016-07-07 06:20:00操作系统版块每日发帖之星
日期:2016-07-04 06:20:00数据库技术版块每日发帖之星
日期:2016-07-03 06:20:00操作系统版块每日发帖之星
日期:2016-07-03 06:20:00数据库技术版块每日发帖之星
日期:2016-07-02 06:20:00操作系统版块每日发帖之星
日期:2016-07-02 06:20:00
发表于 2016-07-22 16:37 |显示全部楼层
用物理机测一下吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP