どうもひろきのだいちです。
最近、初心者にとっていちばんよい言語は・・みたいな話が出てますが、
いちばんよい言語というのはたぶん「近くに一番優しくわかりやすく丁寧に教えてくれる人のいる言語」だと思います。
別に言語なんて関係ないです。
でも、いろいろとできることが違うという意味ではC言語はすごいです。
今日はC言語を使ってプログラムの利用メモリを出力してくれるようなソフトを書いてみました。
こんな風にランダムに生成した数字をquick sortして順番に出力するプログラムがあったとします。
$ ./qsort 10
133557644 467172391
587048537 700406542
924651875 942877877
1231884300 1236726036
1563773570 1858205801
こんな風にランダムに生成した数字をquick sortして順番に出力するプログラムがあったとします。
これにfleafeedとつけるだけで・・・
$fleafeed ./qsort 10
133557644 467172391
587048537 700406542
924651875 942877877
1231884300 1236726036
1563773570 1858205801
-----------fleafeed results------------
--USING STACK : 1160 bytes
--USING HEAP : 0 bytes
--ALLOC times : 0
--FREE times : 0
こんな付加情報を追加してくれるやつを作ってみました。
さらにただ、mallocして放置するというドSなプログラムを
試してみると・・・
-----------fleafeed results------------ --USING STACK : 1076 bytes --USING HEAP : 10000 bytes --ALLOC times : 100 --FREE times : 0
こんなかんじで、計算どおりヒープの数とmallocの数がカウントされてます。
これの作り方の前にちょっと基礎知識を。
わかる人は読み飛ばしてください。まちがった説明するかもなので><
スタックとかヒープとかってのは、プログラムの管理領域であるメモリの役割につけられた名前です。
スタックは関数呼び出しや引数、関数内自動変数などを管理するメモリの領域です。
面倒なので、wikipedia先生に頼ると
・スタック
・コールスタック
こんなかんじのものです。
ヒープとは固定サイズじゃなくて自由に別途に確保できるところにあるメモリーです。
通常mallocでメモリーをもらってfreeで返します。
もらったものは必ず返さないといけないんですが、最近の言語ではGC(ガーベジコレクション)というステキ機能がついていて
変わりに返してくれます。連帯保証人みたいなひとです。
これだけだとあれなのでまたまた、wikipedia先生に・・
・ヒープ領域
・ヒープ構造
理屈は簡単です。
一番最初に一度使われる前のスタック領域を俺色に染め上げて、
プログラムを実行し、なんらかの形で利用されると別の値になってしまうので
一番最後に俺色になっていないところの数を数え上げるという方法です。
そのために
こんな宣言をしてmain関数より前に関数を実行させます。
このときに埋め立てる値を0xf1eafeedとう値にしたので
このプログラムの名前はfleafeedになりました。
適当に16進数で表現できる8文字の英語をいれただけです。
意味はわかりません><
これで、スタックの仕様数はわかりました。
これを
$gcc fleafeed.c -share -fPIC -o libfleafeed.so
のようにしてコンパイルします。これでできたライブラリをリンクしてやれば、スタックの使用量がわかります。
次はヒープです。
ヒープは、よほど無理をしないかぎり、mallocなどから呼ばれるのでこの関数をwrapperしてやればヒープの使用量はわかります。
というわけで、
というような感じでラッパしたいのですが、これだとmallocという名前が衝突してしまいます。
そんなわけで
こんな感じにdlsymのRTLD_NEXTをつかって、mallocのポインタをlibc_mallocという代理人にあずけておきます。
なぜかRTLD_NEXTが#defineされてなかったので即値で対応しました。
ソースコードがあればそこからビルドするときになんとかすればいいんですが、そうではないので事前にライブラリを読み込むようにしてコマンドを呼び出すという方法をとります。
alias fleafeed=LD_PRELOAD=./libfleafeed.so
こんなかんじに。LD_PRELOADはこのライブラリは最初に読み込んじゃって!という環境変数です。
これで準備は万端。
ためしにgccでコンパイルをするときの利用状況を見てみましょう。
$ fleafeed gcc test.c -----------fleafeed results------------ --USING STACK : 6072 bytes --USING HEAP : 832510 bytes --ALLOC times : 1776 --FREE times : 833 -----------fleafeed results------------ --USING STACK : 2272 bytes --USING HEAP : 1810165 bytes --ALLOC times : 863 --FREE times : 48 -----------fleafeed results------------ --USING STACK : 5980 bytes --USING HEAP : 1715525 bytes --ALLOC times : 1185 --FREE times : 355 -----------fleafeed results------------ --USING STACK : 2012 bytes --USING HEAP : 25998 bytes --ALLOC times : 128 --FREE times : 35 -----------fleafeed results------------ --USING STACK : 5840 bytes --USING HEAP : 33885 bytes --ALLOC times : 336 --FREE times : 181
うわなんかいっぱい出たw
プロセス分だけ終わりがあるので、プロセスごとに出力されるようです。
最後に全体のソースコード。
« プログラマのための英文法(笑) – twitterの正しい使い方 »
[...] 次はメモリの消費量です。 これは昨日作ったfleafeedを使ってみます。 C言語でメモリ使用量をカウントする! [...]
Pingback: 日本野望の会-Yabooo.org » Javascriptでカプセル化のコスト | – 07. February 2008 @ 9:33 pm