您的位置:首页 > 编程语言 > C语言/C++

TCMalloc 安装和使用

2016-08-19 15:06 176 查看
前面三篇译文《TCMalloc:线程缓冲的Malloc》、《使用TCMalloc的堆栈检查》、《使用TCMalloc进行堆栈分析》介绍了TCMalloc的基本原理,以及堆栈分析和检查工具,TCMalloc优点很多,比glibc
2.3的malloc快、自带的堆栈工具可以轻松找出内存瓶颈和内存泄漏,给服务器开发指明了一条新的道路。

 


一、下载

 

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 gperftools-2.1.tar.gz

2: #cd gperftools-2.1

3: #./configure

4: #make

5: #make install


 


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

 



1,cd /etc/ 

2,sudo 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
;

11:         p2=new int
;

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是为了优化游戏服务器,解决游戏服务器后期玩家流失后,占用大量内存的浪费,结果发现由于我们游戏服务器为了防止内存碎片和频繁调用new和delete带来的性能损耗,使用了大量的内存池对象(如装备池、技能池、玩家池),这些池都不会调用delete还给系统,所以即使使用了TCMalloc也不会有内存释放,现在也明白了服务器维护的意义,当然这和服务器框架设计很有关系,如果没有这些缓冲池,直接调用new和delete,TCMalloc会是一个很好的选择。

-

Echo Chen:Blog.csdn.net/chen19870707
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ c++11 Protobuf TCMalloc