TCMalloc 安装与使用

TCMalloc 安装和使用

  • Author:Echo Chen(陈斌)
  • Email:chenb19870707@gmail.com
  • Blog:Blog.csdn.net/chen19870707
  • Date:October 20th, 2014

    前面三篇译文《TCMalloc:线程缓冲的Malloc》、《使用TCMalloc的堆栈检查》、《使用TCMalloc进行堆栈分析》介绍了TCMalloc的基本原理,以及堆栈分析和检查工具,TCMalloc长处非常多。比glibc 2.3的malloc快、自带的堆栈工具能够轻松找出内存瓶颈和内存泄漏。给server开发指明了一条新的道路。

    一、下载

    google-perftools:http://code.google.com/p/google-perftools/gperftools-2.1.tar.gz

    libunwind:http://download.savannah.gnu.org/releases/libunwind/libunwind-1.1.tar.gz

    二、libunwind安装

    64位操作系统请先安装 libunwind库,32位操作系统不要安装。libunwind库为基于64位CPU和操作系统的程序提供了主要的堆栈辗转开解功能。当中包含用于输出堆栈跟踪的API、用于以编程方式辗转开解堆栈的API以及支持C++异常处理机制的API。

    1: #tar zxvf libunwind-1.1.tar.gz
    
    2: #cd libunwind-1.1
    
    3: #./configure
    
    4: #make
    
    5: #make install
    


    三、安装google-perftools:

    1: #tar zxvf tar zxvf gperftools-2.1.tar.gz
    
    2: #cd gperftools-2.1
    
    3: #./configure
    
    4: #make
    
    5: #make install
    

    四、TCMalloc库载入到Linux系统中:

    1: echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
    
    2: /sbin/ldconfig
    

    五、使用

    在Makefile中 加入TCMalloc链接,注意:这里为了进行内存泄漏分析,一定要将TCMalloc链接在最后,官方文档里说:堆栈检查器可能误解列在它后面的链接库的一些内存。

    1: # funshion wuhan game studio
    
    2: # Created by zeng jun fei in 2013-08-08
    
    3:
    
    4: CXX = g++
    
    5: # debug
    
    6: CXXFLAGS =  -g -I../BaseCode -I../../CommonSrc -Wall -D_POSIX_MT_ -O0
    
    7: CXXLFLAGS =  -g -Wall -L../bin -lBaseCode -lpthread  -lprotobuf -rdynamic -ltcmalloc
    
    8:
    
    9: # release
    
    10: # CXXFLAGS =  -O3 -g -I../NetworkEngine -Wall
    
    11: # CXXLFLAGS =  -O3 -g -Wall -L../NetworkEngine -lnetwork
    
    12:
    
    13: LIB_NETWORK = ../bin/libBaseCode.a
    
    14:
    
    15: OBJS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
    
    16: SRCS = $(OBJS:%.o=%.cpp)
    
    17: DEPS = $(OBJS:%.o=%.d)
    
    18:
    
    19: ALL_TARGETS = ../bin/GateServer
    
    20:
    
    21: all: $(ALL_TARGETS)
    
    22:
    
    23: -include $(DEPS)
    
    24: $(DEPS): %.d: %.cpp
    
    25:     @$(CXX) -MM $(CXXFLAGS) $< > $@.$$$$; sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$
    
    26:
    
    27: $(OBJS): %.o: %.cpp
    
    28:     $(CXX) -c $(CXXFLAGS) $< -o $@
    
    29:
    
    30: $(ALL_TARGETS): $(OBJS) $(LIB_NETWORK)
    
    31:     $(CXX) $(OBJS) -o $@ $(CXXLFLAGS)
    
    32:
    
    33: clean:
    
    34:     @rm -rf $(OBJS) $(ALL_TARGETS) *.d
    
    35:
    

    六、堆栈检查和分析

    首先,设置pperf的环境变量:export PPROF_PATH=/usr/local/bin/pprof

    測试代码:

    1: #include <iostream>
    
    2: using namespace std;
    
    3:
    
    4: int main()
    
    5: {
    
    6:         int *p = new int();
    
    7:         return 0;
    
    8: }
    

    编译:g++ main.cpp -o main -ltcmalloc -g -O0

    内存泄漏检查: env HEAPCHECK=normal ./main

    结果:

    WARNING: Perftools heap leak checker is active -- Performance may suffer

    Have memory regions w/o callers: might report false leaks

    Leak check _main_ detected leaks of 4 bytes in 1 objects

    The 1 largest leaks:

    Using local file ./main.

    **Leak of 4 bytes in 1 objects allocated from:**

    @ 4007a6 main

    @ 7f1734263d1d __libc_start_main

    @ 4006d9 _start


    If the preceding stack traces are not enough to find the leaks, try running THIS shell command:

    pprof ./main "/tmp/main.54616._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv

    If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1

    If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks more repeatably

    Exiting with error code (instead of crashing) because of whole-program memory leaks

    上面的报告显示有4个字节的内存泄漏,并提示使用pprof进一步跟踪泄漏来源的方法。

    包含normal在内总共同拥有4种泄漏检查方式:minimal,忽略进入main函数之前的初始化过程;normal。报告全部的无法再引用的内存对象。strick,在normal的基础上添加一些额外的检查;draconian。在程序退出的时候存在未释放的内存的情况下报错。


    依据《使用TCMalloc的堆栈检查》,除了前面使用env命令行的全局内存泄漏检查方式外,还能够作对代码段的更加细粒度的泄漏检查。

    这里须要先在源码中包括头文件google/heap-checker.h。

    实例代码例如以下:

    1: #include <cstdio>
    
    2: #include <cstdlib>
    
    3: #include <cassert>
    
    4: #include <google/heap-checker.h>
    
    5: int* fun(int n)
    
    6: {
    
    7:     int *p2;
    
    8:     HeapLeakChecker heap_checker("fun");
    
    9:     {
    
    10:         new int[n];
    
    11:         p2=new int[n];
    
    12:         //delete [] p1;
    
    13:     }
    
    14:     assert(!heap_checker.NoLeaks());
    
    15:     return p2;
    
    16: }
    
    17: int main(int argc,char* argv[])
    
    18: {
    
    19:     int n;
    
    20:     scanf("%d",&n);
    
    21:     int *p=fun(n);
    
    22:     delete [] p;
    
    23:     return 0;
    
    24: }
    

    此外,还能够忽略某些已知的内存泄漏:

    1: #include
    
    2: ...
    
    3: void *mark = HeapLeakChecker::GetDisableChecksStart();
    
    4: <leaky code>
    
    5: HeapLeakChecker::DisableChecksToHereFrom(mark);
    

    感觉跟valgrind效果差点儿相同,可是valgrind还能查出内存越界。更加优秀。

    七、总结

    本来研究TCMalloc是为了优化游戏server,解决游戏server后期玩家流失后。占用大量内存的浪费。结果发现因为我们游戏server为了防止内存碎片和频繁调用new和delete带来的性能损耗。使用了大量的内存池对象(如装备池、技能池、玩家池),这些池都不会调用delete还给系统,所以即使使用了TCMalloc也不会有内存释放,如今也明确了server维护的意义,当然这和server框架设计非常有关系,假设没有这些缓冲池,直接调用new和delete,TCMalloc会是一个非常好的选择。


    -

    Echo Chen:Blog.csdn.net/chen19870707

    -

  • 版权声明:本文博主原创文章。博客,未经同意不得转载。
    原文链接: https://www.cnblogs.com/lcchuguo/p/4849447.html

    欢迎关注

    微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/222508

    非原创文章文中已经注明原地址,如有侵权,联系删除

    关注公众号【高性能架构探索】,第一时间获取最新文章

    转载文章受原作者版权保护。转载请注明原作者出处!

    (0)
    上一篇 2023年2月13日 上午11:45
    下一篇 2023年2月13日 上午11:46

    相关推荐