前面三篇譯文《TCMalloc:線程緩衝的Malloc》、《使用TCMalloc的堆棧檢查》、《使用TCMalloc進行堆棧分析》介紹了TCMalloc的基本原理,以及堆棧分析和檢查工具,TCMalloc優勢不少,比glibc 2.3的malloc快、自帶的堆棧工具能夠輕鬆找出內存瓶頸和內存泄漏,給服務器開發指明瞭一條新的道路。node
google-perftools:http://code.google.com/p/google-perftools/gperftools-2.1.tar.gzios
libunwind:http://download.savannah.gnu.org/releases/libunwind/libunwind-1.1.tar.gzshell
64位操做系統請先安裝 libunwind庫,32位操做系統不要安裝。libunwind庫爲基於64位CPU和操做系統的程序提供了基本的堆棧展轉開解功能,其中包括用於輸出堆棧跟蹤的API、用於以編程方式展轉開解堆棧的API以及支持C++異常處理機制的API。編程
#tar zxvf libunwind-1.1.tar.gz #cd libunwind-1.1 #./configure #make #make install
1 #tar zxvf tar zxvf gperftools-2.1.tar.gz 2 #cd gperftools-2.1 3 #./configure 4 #make 5 #make install
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
首先,設置pperf的環境變量:export PPROF_PATH=/usr/local/bin/pprofapp
測試代碼:框架
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
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 |
上面的報告顯示有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 }
此外,還能夠忽略某些已知的內存泄漏:
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會是一個很好的選擇。
原文連接:http://blog.csdn.net/chen19870707/article/details/40301783