Google Heap Profiler

功能及原理

先來大概介紹下Google Heap Profiler,大體有三類功能:node

能夠分析出在程序的堆內有些什麼東西程序員

定位出內存泄露web

可讓咱們知道哪些地方分配了比較多的內存正則表達式

大概的原理就是使用tcmalloc 來代替malloc calloc new等等,這樣Google Heap Profiler就能知道內存的分配狀況,從而分析出內存問題。shell

 

安裝:

一.  安裝與簡介 sass

(1) 下載源碼包。路徑https://code.google.com/p/google-perftools/多線程

(2) ./configureapp

(3) make (若是報錯,則./configure --enable-frame-pointers)dom

(4) make  installsvg

頭文件和庫文件分別在/usr/local/inlcude/google/和/usr/local/lib/下。須要設置環境變量export LD_LIBRARAY_PATH=/usr/local/lib。跟valgrind的profiler工具的不一樣之處是,Google perftools使用在源程序中插入profiler代碼的方式,而不是valgrind的虛擬機方式,因此Google perftools以庫文件的形式提供了一系列函數接口。爲了使用圖形化結果還須要安裝gv,可以使用apt-get安裝:sudo apt-get install gv。 

    Google Perftools包括三個工具(注:包括tcmalloc應該是4個),三個工具均支持多線程程序,如下分別介紹。 

 

 

用法

首先須要把tcmalloc連接到咱們須要分析的程序中, 固然咱們也能夠動態load 這個lib,可是爲了簡單起見,仍是推薦你們連接這個lib到本身的程序中。

連接以後,咱們接下來的任務就是獲得內存分析的dump文件,咱們有兩種方法:

    1.    靜態dump方法:

        直接定義一個環境變量HEAPPROFILE來指定dumpprofile文件的位置,如:/tmp/test.log,它將會在/tmp/目錄下生成不少相似/tmp/test.log.0003.heap文件名的文件

        env HEAPPROFILE="/tmp/test.log" /test/testprog

     2.    動態dump方法:

咱們能夠調用Google Heap Profiler的API來控制何時dump出內存的profiler文件,這樣更加靈活,爲此,咱們必須包含heap-profiler.h這個頭文件。

HeapProfilerStart() 用來開始內存分析

HeapProfilerStop().  用來終止內存分析

這樣就只會在開始和結束之間產生dump profiler文件。

 

 

如:

#if 1

#include "acconfig.h"

#ifdefHAVE_GPERFTOOLS_HEAP_PROFILER_H

        #include<gperftools/heap-profiler.h>

#else

        #include <google/heap-profiler.h>

#endif

 

#ifdefHAVE_GPERFTOOLS_MALLOC_EXTENSION_H

        #include<gperftools/malloc_extension.h>

#else

        #include<google/malloc_extension.h>

#endif

#include"common/environment.h"

#endif

 

void  heap_profiler_start()

{

 char profile_name[PATH_MAX];

 get_profile_name(profile_name, sizeof(profile_name));

 HeapProfilerStart(profile_name);

}

void  heap_profiler_stop()

{

 HeapProfilerStop();

}

void  heap_profiler_dump(const char *reason)

{

 HeapProfilerDump(reason);

}

bool  heap_profiler_running()

{

 return IsHeapProfilerRunning();

}

void  heap_release_free_memory()

{

 MallocExtension::instance()->ReleaseFreeMemory();

}

void  heap_profiler_stats(char *buf, int length)

{

 MallocExtension::instance()->GetStats(buf, length);

}

 

選項

  •  HEAP_PROFILE_ALLOCATION_INTERVAL

程序內存每增加這一數值以後就dump 一次內存,默認是1G (1073741824)

  •  HEAP_PROFILE_INUSE_INTERVAL

程序若是一次性分配內存超過這個數值dump 默認是100K

 

查看內存dump文件

這麼dump文件生成以後,咱們接下來就能夠查看內存的分佈狀況,如:

pprof --pdf /test/testProg/tmp/test.log.0001.heap

就是以pdf的形式來顯示這個dump文件,固然咱們也可使用其餘的格式來顯示。

  

這就是全部可支持的格式。

注:若是pprof 運行出錯,請檢查時候已經正確安裝,若是出現sh: dot: command not found 這個錯誤,就是須要安裝yum install graphviz -y  

咱們也能夠專門focus在一些包含某些關鍵字的路徑上,也能夠忽略相關的路徑

--focus

--ignore

pprof --pdf --focus=CData /test/testProg/tmp/test.log.0001.heap

使用形式 

須要安裝:graphviz安裝:

graphviz有多種安裝方式,源碼及發行包。

當前最新版源碼下載:

http://120.221.32.79:6510/www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.38.0.tar.gz

 

  pprof的使用形式都是: pprof --option [ --focus=<regexp> ] [ --ignore=<regexp> ] [--line or addresses or functions] 可執行文件路徑  對應的profile路徑。方括號中的項目是可選項目。<regexp>表示正則表達式

 

形如:pprof –gif /root/axw/my_biotest/biotestclient.1940324.profile.0055.heap > graph.gif

 

★options的選項以下:

--text             Generate text report

  --callgrind         Generate callgrindformat to stdout

  --gv               Generate Postscript and display

  --evince           Generate PDF and display

  --web              Generate SVG and display

  --list=<regexp>     Generate source listing ofmatching routines

  --disasm=<regexp>   Generate disassembly of matching routines

  --symbols           Printdemangled symbol names found at given addresses

  --dot              Generate DOT file to stdout

  --ps               Generate Postcript to stdout

  --pdf              Generate PDF to stdout

  --svg              Generate SVG to stdout

  --gif              Generate GIF to stdout

  --raw              Generate symbolized pprof data (useful with remote fetch)

 

★一些宏

HEAP_PROFILE_ALLOCATION_INTERVAL

程序內存每增加這一數值以後就dump 一次內存,默認是1G (1073741824)

         HEAP_PROFILE_INUSE_INTERVAL

程序若是一次性分配內存超過這個數值dump 默認是100K,

字符統計輸出

命令:pprof --text ./RBtree ./RBtree.prof 

關於文本風格輸出結果

序號

說明

1

分析樣本數量(不包含其餘函數調用)

2

分析樣本百分比(不包含其餘函數調用)

3

目前爲止的分析樣本百分比(不包含其餘函數調用)

4

分析樣本數量(包含其餘函數調用)

5

分析樣本百分比(包含其餘函數調用)

6

函數名

 

字符統計結果: 

         501  62.2%  62.2%      714  88.6% RBTree::insert

          84  10.4%  72.6%       84  10.4% RBTree::defaultCmp

          80   9.9%  82.5%      154  19.1% RBTree::nodeCmp

          61   7.6%  90.1%       73   9.1% RBTree::insertFixup

          47   5.8%  95.9%       47   5.8% malloc_trim

           9   1.1%  97.0%      746  92.6% main

           6    0.7%  97.8%        6   0.7% RBTree::rightRotate

           6   0.7%  98.5%        6   0.7% RBTree::leftRotate

           5   0.6%  99.1%        5   0.6% malloc

           3   0.4%  99.5%        3   0.4% operator new

           3   0.4%  99.9%        3   0.4% random_r

           1   0.1% 100.0%        1   0.1% rand

           0   0.0% 100.0%      755  93.7% __libc_start_main 

每行對應一個函數的統計。第一,二列是該函數的本地採樣(不包括被該函數調用的函數中的採樣次數)次數和比例,第三列是該函數本地採樣次數佔當前全部已統計函數的採樣次數之和的比例。第四,五列是該函數的累計採樣次數(包括其調用的函數中的採樣次數)和比例。 

 

Text輸出結果分析

14  2.1% 17.2%       58   8.7%std::_Rb_tree::find

含義以下:

14:find函數花費了14個profiling samples

2.1%:find函數花費的profiling samples佔總的profilingsamples的比例

17.2%:到find函數爲止,已經運行的函數佔總的profiling samples的比例

58:find函數加上find函數裏的被調用者總共花費的profilingsamples

8.7%:find函數加上find函數裏的被調用者總共花費的profilingsamples佔總的profiling samples的比例

std::_Rb_tree::find:表示profile的函數

ps: 100samples a second,因此得出的結果除以100,得秒單位

 

 

圖片輸出

命令

Pprof --pdf /root/biotest /var/log/client.1940324.profile.0047> graph.gif  生成的gif統計圖以下。

結果如圖:

 

 

    圖中每一個節點對應一個函數,節點中的文字分別爲類名,函數明,本地採樣次數比例和累計採樣次數比例(若是跟本地相同則省略)。每條邊表示一個函數調用關係:caller調用callee,邊上的數字表示callee中由於caller調用而被採樣的次數。 

    pprof若是不帶任何選項調用(只有可執行文件路徑和profile文件路徑)則進入互動模式,在互動模式下可以使用gv,gif,text等命令來替代前面介紹的帶選項的pprof調用。

比較dump文件

命令:pprof --pdf --base /tmp/test.log.0001.heap /test/testProg/tmp/test.log.0101.heap

 

爲了知道在某一段時間內的內存分佈狀況,或者須要瞭解某段時間內有沒有內存泄露,咱們就須要用到diff咱們的dump文件

例如:pprof --pdf --base /tmp/test.log.0001.heap /test/testProg/tmp/test.log.0101.heap

比較了第一個dump文件與第101個文件的差別,並且結果以pdf的形式顯示

Heap Checker 

    堆內存泄漏檢測工具。使用簡單,先在連接被檢查程序的時候用-ltcmalloc選項鍊接Goolge Perftools的堆內存管理庫tcmalloc(tcmalloc會替代C的堆內存管理庫),而後每次用命令行「env HEAPCHECK=normal 可執行程序路徑」來進行檢查,其中檢查形式normal能夠替換成其餘值,檢查的結果會以屏幕報告的形式給出。如下給出一個實例: 

# cat test_heap_checker.cpp
#include <cstdio>
#include <cstdlib>
int* fun(int n)
{
    int *p1=new int[n];
    int *p2=new int[n];
    return p2;
}
int main()
{
    int n;
    scanf("%d",&n);
    int *p=fun(n);
    delete [] p;
    return 0;
}
# g++ -O0 -g test_heap_checker.cpp -ltcmalloc -o test_heap_checker 

# env HEAPCHECK=normal /home/hongcheng/mycode/google-perftools-tests/test_heap_checker
WARNING: Perftools heap leak checker is active -- Performance may suffer
100
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 400 bytes in 1 objects
The 1 largest leaks:
Leak of 400 bytes in 1 objects allocated from:
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof /home/hongcheng/mycode/google-perftools-tests/test_heap_checker "/tmp/test_heap_checker.13379._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
Exiting with error code (instead of crashing) because of whole-program memory leaks 

    上面的報告顯示有400個字節的內存泄漏,並提示使用pprof進一步跟蹤泄漏來源的方法。 

    包括normal在內總共有4種泄漏檢查方式:minimal,忽略進入main函數以前的初始化過程;normal,報告全部的沒法再引用的內存對象;strick,在normal的基礎上增長一些額外的檢查;draconian,在程序退出的時候存在未釋放的內存的狀況下報錯。 

    除了前面使用env命令行的全局內存泄漏檢查方式外,還能夠做對代碼段的更加細粒度的泄漏檢查。這裏須要先在源代碼中包含頭文件google/heap-checker.h。下面是一個檢查代碼段的實例: 

       HeapLeakChecker heap_checker("test_foo");
    {
        code that exercises some foo functionality;
        this code should preserve memory allocation state;
    }
    if (!heap_checker.SameHeap()) assert(NULL == "heap memory leak"); 

  在進入代碼段以前創建當前堆內存使用狀況的snapshot,而後在結束代碼段的時候經過與記錄的snapshot對比檢查是否有泄漏。方法NoLeaks()也能夠用在這裏。下面是一個實例: 

    #include <cstdio>
    #include <cstdlib>
    #include <cassert>
    #include <google/heap-checker.h>
    int* fun(int n)
    {
        int *p2;
        HeapLeakChecker heap_checker("fun");
        {
            new int[n];
            p2=new int[n];
            //delete [] p1;
        }
        assert(!heap_checker.NoLeaks());
        return p2;    
    }
    int main(int argc,char* argv[])
    {
        int n;
        scanf("%d",&n);
        int *p=fun(n);
        delete [] p;
        return 0;
    } 

    注意被檢查程序的main函數形式必須爲帶2個參數的形式,不然會在編譯時報告重複定義。運行env命令行將會報告assert失敗。

    另外,還能夠跳過某些代碼段的檢查,方式以下: 

        {
        HeapLeakChecker::Disabler disabler;
        <leaky code>
    } 

  <leaky code>處的代碼將被heap-checker忽略。

 

[root@inspur178 my_biotest]# HEAPCHECK=normal ./biotest -w 1/biotest1/ -s 34 -b 4096

WARNING: Perftools heap leakchecker is active -- Performance may suffer

------processID -> 2391436

thread index : 1 -> /1.dat

begin write...

------processID -> 2391436

input command:  end write .

thread [1] complete !

 

c:(null) p:(null)

input command:  quit

c:quit p:(null)

wait join all the thread...

all thread over!!!

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

Leak check _main_ detected leaksof 144 bytes in 1 objects

The 1 largest leaks:

Using local file ./biotest.

Leak of 144 bytes in 1 objectsallocated from:

    @7fa290af3d88 icfs_os_setxattr

    @7fa290aef8c9 IcfsContext

    @7fa290aebec5 common_preinit

    @7fa2909207bb icfs_create

    @4037bc main

    @7fa28fa23d1d __libc_start_main

    @4016e9 _start

 

 

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

 

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

 

If you are still puzzled aboutwhy the leaks are there, try rerunning this program withHEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or withHEAP_CHECK_MAX_POINTER_OFFSET=-1

If the leak report occurs in asmall fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of fewhundred MB or with TCMALLOC_RECLAIM_MEMORY=false, it might help find leaks morere

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

 
 

Google Heap Profiler使用方法

最近在查找內存泄露的問題,使用了一些工具來查找問題,定位問題,可是工具都有各自的優劣,在咱們實際的使用過程中,只有各類工具結合使用才能發揮最大的效用。 因爲項目須要,最近也開始使用Google H...
  • jhzhou
  • jhzhou
  • 2012年02月10日 10:12
  • 9922

用google-perftool分析程序的內存/CPU使用

最近,用到了google-perftool分析程序的內存和CPU的使用狀況,總結一下使用的一些方法和體會,分享給有須要的朋友。首先,說說google-perftool,它是由google開發的用來分析...
  • zm_21
  • zm_21
  • 2014年06月30日 17:41
  • 1960
 

【揭祕】程序員升職加薪的捷徑來了!

在崗5年,總想着閒下來的時候應該如何安排本身的程序人生呢?無心中看到這個!眼睛亮了..

用google-perftool分析程序的內存/CPU使用

最近,用到了google-perftool分析程序的內存和CPU的使用狀況,總結一下使用的一些方法和體會,分享給有須要的朋友。首先,說說google-perftool,它是由google開發的用來分析...

ceph存儲 Google perftools工具內存檢測以及性能分析

一. 安裝與簡介      從主頁http://code.google.com/p/google-perftools/downloads/list下載源碼包,解壓後使用命令序列./configu...
  • skdkjxy
  • skdkjxy
  • 2015年08月04日 09:17
  • 2236

使用ceoh-deploy工具快速部署ceph--先決條件準備

最近按照ceph的官方文檔來部署ceph,發現遇到了很多的問題,其中不少問題都是安裝部署的時候遇到的坑,在這裏提出來和你們一塊兒分享探討,若有不足之處歡迎評論。筆者這裏使用的操做系統:CentOS7.2...
 

使用ceoh-deploy工具快速部署ceph--部署

最近按照ceph的官方文檔來部署ceph,發現遇到了很多的問題,其中不少問題都是安裝部署的時候遇到的坑,在這裏提出來和你們一塊兒分享探討,若有不足之處歡迎評論。存儲集羣部署在controllernode...

OpenStack 整合使用Ceph實現(Copy-On-Write)克隆 (筆記)

本文使用的系統環境: CentOS6.5 四臺機器 規劃以下: HostName IP        安裝服務 c01 192.168.40.101 mon mds osd c02 19...
  • mrz001
  • mrz001
  • 2014年08月28日 14:46
  • 937

如何在ceph中新增google unit test總結

如何在ceph中新增unit test總結

ceph perf counter 源碼分析及使用

ceph perf counter 源碼分析及使用示例1 enum { 2 test_perfcounter_first = 200, 3 test_perfcount...

google開源的C++性能分析工具 - gperftools

gperftools是Google提供的一套工具,其中的一個功能是CPU profiler,用於分析程序性能,找到程序的性能瓶頸。 安裝 gperftools:http://code.google...
相關文章
相關標籤/搜索