kubo39's blog

ただの雑記です。

dmdの-profileオプション

dmdにはWindowsもしくはx86系のアーキテクチャの場合は -profile オプションで実行したプログラムのプロファイルを取得することができます。

dmdのmanを見ると、

-profile
       Profile the runtime performance of the generated code

こういう風に確認できます。

実際に適当なプログラムで計測ととってみます。結果は trace.log というファイルに書き込まれます。

全部貼ると長いので一部だけとってくると、

...
======== Timer Is 3579545 Ticks/Sec, Times are in Microsecs ========

  Num          Tree        Func        Per
  Calls        Time        Time        Call

     12       46493       46493        3874     _D3std5stdio4File17LockingTextWriter10__T3putTaZ3putMFNfaZ12trustedFPUTCFNbNiNeiPS4core4stdc5stdio8_IO_FILEZi
     60        3872        3872          64     @safe void std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(immutable(char)[])
      1       91349        3206        3206     _Dmain
     12       76720        3079         256     @safe void std.stdio.File.write!(cssparser.tokenizer.Token, char).write(cssparser.tokenizer.Token, char)
     12       26863        3075         256     @safe uint std.format.formattedWrite!(std.stdio.File.LockingTextWriter, char, cssparser.tokenizer.Token).formattedWrite(std.stdio.File.LockingTextWriter, const(char[]), cssparser.tokenizer.Token)
     13        7578        2778         213     cssparser.tokenizer.Token cssparser.tokenizer.Tokenizer.nextToken()
     12       11926        2655         221     @safe void std.format.formatElement!(std.stdio.File.LockingTextWriter, immutable(char)[], char).formatElement(std.stdio.File.LockingTextWriter, immutable(char)[], ref std.format.FormatSpec!(char).FormatSpec)
     24        3147        2450         102     @safe bool std.format.FormatSpec!(char).FormatSpec.writeUpToNextSpec!(std.stdio.File.LockingTextWriter).writeUpToNextSpec(std.stdio.File.LockingTextWriter)
     16        2410        2410         150     pure nothrow ref @trusted std.array.Appender!(immutable(char)[]).Appender std.array.Appender!(immutable(char)[]).Appender.__ctor(immutable(char)[])
     17        3569        2199         129     pure @safe void std.format.formatChar!(std.array.Appender!(immutable(char)[]).Appender).formatChar(std.array.Appender!(immutable(char)[]).Appender, const(dchar), const(char))
     41        2054        1998          48     pure nothrow @trusted void std.array.Appender!(immutable(char)[]).Appender.ensureAddable(ulong)
     12       20264        1691         140     @safe void std.format.formatValue!(std.stdio.File.LockingTextWriter,
...

だいたいこんな感じの出力結果になります。

これの実体はdruntimeの rt.trace.QueryPerformanceCounter というあたりなのですが、このQueryPerformanceCounterというのは同名のWin32 APIが元になっています。

実際Windowsの場合はこのQueryPerformanceCounterが使われていますが、Linux x86系ではWin32 APIはもちろん使うことができません。

なのでどうしているかというと、rdtsc命令を使ってタイプスタンプ値を取得しています。

ちょうど wiki.dlang.org にも rdtscを使った時間計測方法 がのっています。(どうでもいいですがちょっと情報が古いですね、、今はstd.perfではなくrt.traceにありますし-gtオプションもdeprecated扱いです。)

ちなみに rdtsc で取得できるタイムスタンプ値はコア毎に違っているため、コンテキストスイッチが発生すると正しくない値が取得される場合があるので注意が必要です。