リード開発メモ

大阪のソフトウェア会社です。 技術的な事柄についてのメモとしてブログを始めます。

Fedora

Google Performance Tools を使う(その2)

今回は gperftools(Google Performance Tools) を使ってメモリリークを検出してみたいと思う。

下のコードをコンパイルして試す。関数aと関数bでわざとメモリリークを発生させている。
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 

int a(void) {
	char* x = new char[4]; // memory leak
	x[0]='x';
	int i=0,g=0;
	while(i++<100000)
	{
		g+=i;
	}
	return g;
}
int b(void) {
	char* y = new char[4]; // memory leak
	y[0]='y';
	char* z = new char[4];
	z[0]='z';
	int i=0,g=0;
	while(i++<400000)
	{
		g+=i;
	}
	delete[] z;
	return g;
}

int main(int argc, char** argv)
{
	int iterations;

	if(argc != 2)
	{
		printf("Usage %s <No of Iterations>\n", argv[0]);
		exit(-1);
	}
	else
		iterations = atoi(argv[1]);

	printf("No of iterations = %d\n", iterations);

	struct timeval s, e;
	gettimeofday(&s, NULL);

	while(iterations--)
	{
		a();
		b();
	}

	gettimeofday(&e, NULL);
	printf("time = %lf\n", (e.tv_sec - s.tv_sec) + (e.tv_usec - s.tv_usec)*1.0E-6);
	return 0;
}

Makefile は以下のとおり。リンクフラグに -ltcmalloc を追加している。
# Makefile
program = gpttest
objs = gpttest.o

CC = g++
CFLAGS = -g -Wall

LD = g++
LDFLAGS = -ltcmalloc

.SUFFIXES: .c .o

$(program): $(objs)
	$(LD) -o $(program) $(LDFLAGS) $^

.c.o:
	$(CC) $(CFLAGS) -c $<

.PHONY: clean
clean:
	$(RM) $(program) $(objs)

make が済んだら、以下のようにして実行する。1行目は libtcmalloc.so.4 がないと怒られるため、パスを通している。そして3行目の環境変数 HEAPCHECK に値をセットすることで、実行時にメモリリークのチェックが行われるようになる。
> export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
> export PPROF_PATH=/usr/local/bin/pprof
> export HEAPCHECK=strict
> ./gpttest 3

実行後、以下のような表示が行われ、メモリリークが発生していることがわかる。
[user1@localhost gperftools-test]$ sh gpttest.sh
WARNING: Perftools heap leak checker is active -- Performance may suffer
No of iterations = 3
time = 0.002770
Leak check _main_ detected leaks of 24 bytes in 6 objects
The 2 largest leaks:
Using local file ./gpttest.
Leak of 12 bytes in 3 objects allocated from:
	@ 4007f6 a
	@ 40091a main
	@ 309721ea4d __libc_start_main
Leak of 12 bytes in 3 objects allocated from:
	@ 400840 b
	@ 40091f main
	@ 309721ea4d __libc_start_main


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

pprof ./gpttest "/tmp/gpttest.4870._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 repea
Exiting with error code (instead of crashing) because of whole-program memory leaks

中ほどにpprof で始まる行があり、このコマンドを実行すればgvでメモリリークの発生場所を表示してくれる。のだが、gv は入っていないため text で表示してみる。最後の --gv を --text に変える。
> pprof ./gpttest "/tmp/gpttest.4870._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --text

実行結果は以下のとおり。メモリリークの原因となったファイルと行番号を教えてくれる。
Using local file ./gpttest.
Using local file /tmp/gpttest.4870._main_-end.heap.
Total: 6 objects
       3  50.0%  50.0%        3  50.0% a /home/yamashita/gperftools-test/gpttest.c:6
       3  50.0% 100.0%        3  50.0% b /home/yamashita/gperftools-test/gpttest.c:16
       0   0.0% 100.0%        6 100.0% __libc_start_main ??:0
       0   0.0% 100.0%        3  50.0% main /home/yamashita/gperftools-test/gpttest.c:48
       0   0.0% 100.0%        3  50.0% main /home/yamashita/gperftools-test/gpttest.c:49

graphviz を使うことでグラフィカルに表示することもできる。 まずはgraphviz のインストール。
> yum install graphviz

続いて gperftool の結果を処理する。gvのところをdotに変える。
> pprof ./gpttest "/tmp/gpttest.4870._main_-end.heap" --inuse_objects --lines --heapcheck  --edgefraction=1e-10 --nodefraction=1e-10 --dot > gpttest.dot
> dot -T png gpttest.dot > gpttest.png

出力された画像が次だ。
gpttest

以上。

Google Performance Tools を使う(その1)

Fedora9 x86_64上で C++ を書いているが、メモリリークを調べるため gperftools(Google Performance Tools) を利用してみる。

gperftools は以下のサイトからダウンロードできる。
http://goog-perftools.sourceforge.net/

gperftools は元のプログラムにリンクするだけで以下の4機能を利用できるようになる。
・TC Malloc
・Heap Checker
・Heap Profiler
・Cpu Profiler

TC Malloc はmallocをより高速なメモリ確保を行う実装に挿げ替えるというもので、リンクするだけでパフォーマンスがよくなる。

それ以外の3機能は、それぞれ専用の環境変数を設定してからプログラムを実行することで、プロファイルを行う。結果はファイルに出力されるので、後で出力ファイルを解析する。メモリリークの検出はHeap Checker を使う。

以下に gperftools のインストール手順を示す。
yum install libunwind

cd /tmp
wget https://gperftools.googlecode.com/files/gperftools-2.1.zip
unzip gperftools-2.1.zip
cd gperftools-2.1
./confire --enable-frame-pointers 
make

Fedora9 x86_64 の環境では、gperftoolsのコンパイルには libunwind が必要となるので、まず libunwind をインストールした。また configure は --enable-frame-pointers を指定する必要があった。

以上でインストールは完了なのだが、インストールが終わったらリンクフラグ -ltcmalloc を指定して、プログラムをリンクし直す。

ここで実行してみると libtcmalloc.so.4 がないというエラーが出た。このファイルは /usr/local/lib に存在するのだが、パスを通す必要があるようだ。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

これで無事実行できた。

以上で gperftools の導入は完了である。

アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

livedoor 天気