Hello, world! 統計

なんかまず kernel はどうやったもんかなと思ったのでやめておくことに。端末とかも追わないので不完全ではありますが、趣旨としては、以下の非常に高度な技術が詰め込まれたコードがどれだけ大変なことになって実行されているかというようなことを肌で感じたいなと。数字を肌で感じるのは割と大事だと思うんですよね。

#include <stdio.h>
int main() {
    puts("Hello, world!");
}

このコードをデバッグ情報つきでコンパイルしたところ、 8812Bytes というところのようでした。ゴルフ的観点においてかなり大規模なコードと言えます。いやまぁそういうのはどうでもいいとして。

でまぁ計測結果によると、ユーザランドでの総実行ステップ数は 92165 、実行したバイト数はループなんかの重複を無視して空間的な意味で考えると 29700 Bytes で、ループなどでの重複を入れると 342414 Bytes 。

うち hello 自身は、たったの 95 ステップで 353Bytes の空間を 365Bytes 実行。

残りの 9 万ステップ以上はどこで使ったかというと、 libc で 7007 ステップ、 5053Bytes の空間を 21695Bytes 実行、ダイナミックローダ ld-2.7.so で 85063 ステップ、 24294Bytes の空間を 320354Bytes 実行、とのことでした。

ユーザランドだけでも、実に 1000倍程度の時間をプログラム本体以外で過ごしたことになります。絵にするとこんな感じ。

Step counts in Hello, world!

そして気になる(ならないと思うけど)最もたくさん実行された命令は mov でした。そらそうですね。絵にするとこんな感じ。

Opcode statistics of Hello, world!

syscall は 34 回呼ばれたようでした。内訳を見てみると、

Syscall statistics of Hello, world!

いよいよだからどうしたという感です。

ついでに FizzBuzz とかどんなもんかねとやってみたところ、 136260 step だそうです。

Step counts in FizzBuzz

でなんか実行した命令の列からソースを読む新しいコードリーディングのありかたというのをやりたかったんだけど、あまりに多くてめんどくさいのでやめた。しかしちょっと読んでみた感じそんなに悪くもないみたいだったかなぁと。

今回のために使ったソース。

http://shinh.skr.jp/binary/stepcnt.tgz

以下のように実行。

% gcc -g -I. stepcnt.c -o stepcnt
% gcc -g hello.c -o hello
% ./stepcnt ./hello > trace 2>&1
% ruby stepcnt.rb

実装は単にステップ実行をひたすら繰り返してるだけです。 /proc/self/maps 見てるから linux 限定。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h