偶には再帰メソッドの消費メモリーが気になるので、
どうやって調べるのを調べたら、Linux OSに付いているcheckstack.pl
を見つけた。
ソースをgistに上げました。checkstack.pl
ちなみに、154行目のnext if ($size < 100);
をコメントアウト済み。
そうすれば、スタックサイズが100以下のメソッドもリストアップしてくれた。
テスト用のソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
使う
macなのでobjdumpではなくgobjdumpを使う。homebrewでインストールすると便利
g++ stack_test.cpp
gobjdump -d a.out | checkstack
結果
0x000100000e14 __Z14func_arr_int_2v []: 16
0x000100000e33 __Z14func_arr_int_2v []: 16
0x000100000e44 __Z14func_arr_int_3v []: 32
0x000100000e63 __Z14func_arr_int_3v []: 32
0x000100000e74 __Z14func_arr_int_4v []: 32
0x000100000e93 __Z14func_arr_int_4v []: 32
0x000100000ea4 __Z10func_pointv []: 16
0x000100000ebe __Z10func_pointv []: 16
0x000100000ed4 _main []: 32
0x000100000f09 _main []: 32
0x000100000f14 __ZN5PointC1Eff []: 16
0x000100000f39 __ZN5PointC1Eff []: 16
今のコンパイラって結構やってくれるな。
func1
ではレジストで操作したからスタック消費はなし。
func_arr_int_1
がスタック消費がないのは驚いた。size = 1のarrayは最適化されてなくなったみたい。
x64マシンなので、メモリー最小単位は16byteになるのか?
func_arr_int_2
は16byte。func_arr_int_3
は実際24byteだと思うが、スタックサイズは32byteになった。メモリーは2単位取ったね。
checkstack.plの原理
elsif ($arch =~ /^x86(_64)?$/ || $arch =~ /^i[3456]86$/) {
#c0105234: 81 ec ac 05 00 00 sub $0x5ac,%esp
# or
# 2f60: 48 81 ec e8 05 00 00 sub $0x5e8,%rsp
$re = qr/^.*[as][du][db] \$(0x$x{1,8}),\%(e|r)sp$/o;
$dre = qr/^.*[as][du][db] (%.*),\%(e|r)sp$/o;
}
逆コンパイルされたコードの中のadd
, sub
, esp
, rsp
を探して、スタックサイズを計算するらしい。