PR

プロファイルにDTraceやInstrumentsを利用する

 Mac OS XやSolarisといったOSでは,GHCの並列プロファイラの代わりにDTrace(Dynamic Trace)を利用することもできます(参考リンク)。GHCのRTSでは,RTSで実行されるさまざまなイベントに対してあらかじめプローブ(Probe)が設置されます。これにより,DTraceでもRTS内の各イベントの追跡情報を取得できるのです。なお,GHC 7.2.1の時点では,DTraceを利用するための機能はFreeBSDには対応していません。

 GHCのプロファイラや並列プロファイラとは異なり,DTraceを利用する場合には,Haskellプログラムをビルドする際に特別なコンパイル・オプションやリンク・オプションを与える必要はありません。GHCiやHaskellプログラムを実行するのとは別プロセスのプロンプト画面で,DTraceを実行するだけでOKです(現在のところ,Mac OS X上でDTraceの-cオプションを使ってHaskellプログラムを実行した場合には,RTS内の各イベントの追跡情報を取得できません。そのため,DTraceの-cオプションを使うのではなく,別プロセスのプロンプト画面でDTraceを実行する必要があります)。

$ ghc -O2 -threaded ParallelTest.hs -rtsopts

$ ./ParallelTest +RTS -N

~ 略 ~ 

$ ./ParallelTest +RTS -N

~ 以下略 ~

●別のプロンプト

$ sudo dtrace -P 'HaskellEvent*' -Z
dtrace: description 'HaskellEvent*' matched 0 probes
CPU     ID                    FUNCTION:NAME
  0  65125                  hs_init:startup 
  0  65103   initCapabilities:capset-create 
  0  65102 initCapabilities:capset-assign-cap 
  0  65102 initCapabilities:capset-assign-cap 
  0  65107       createThread:create-thread 
  0  65135 scheduleWaitThread:thread-runnable 
  0  65122              schedule:run-thread 
  0  65128        suspendThread:stop-thread 
~ 略 ~
  1  65128        suspendThread:stop-thread 
  1  65123          resumeThread:run-thread 
  1  65128        suspendThread:stop-thread 
  1  65123          resumeThread:run-thread 
  1  65127             schedule:stop-thread 
^C

$ sudo dtrace -n 'HaskellEvent*:::gc-start' -n 'HaskellEvent*:::gc-end' -Z
dtrace: description 'HaskellEvent*:::gc-start'matched 0 probes
dtrace: description 'HaskellEvent*:::gc-end' matched 0 probes
CPU     ID                    FUNCTION:NAME
  0  65113         yieldCapability:gc-start 
  0  65110           yieldCapability:gc-end 
  0  65113         yieldCapability:gc-start 
  0  65110           yieldCapability:gc-end 
  0  65113         yieldCapability:gc-start 
  0  65110           yieldCapability:gc-end 
  0  65113         yieldCapability:gc-start 
  0  65110           yieldCapability:gc-end 
~ 略 ~
  1  65113         yieldCapability:gc-start 
  1  65110           yieldCapability:gc-end 
  1  65112            scheduleDoGC:gc-start 
  1  65109              scheduleDoGC:gc-end 
^C

 DTraceではDというスクリプト言語が用意されており,これを利用することで,取得したデータを加工できます。興味のある方はDTraceやDについて学んでみてください。「Solaris 動的トレースガイド」(原文はSolaris Dynamic Tracing Guide)というドキュメントや「DTrace: Dynamic Tracing in Oracle Solaris, Mac OS X and FreeBSD」,「C/C++プログラマのためのDTrace入門」といった記事が参考になります。現時点では,Haskellプログラムのプロファイルを取ったり,デバッグしたりするのに便利なDスクリプトは,Haskellコミュニティではまだ提供されていないようです。

 Mac OS Xでは,Xcodeで提供されているInstrumentsというツールをDTraceと連携させて利用できます。Haskellプログラムの振る舞いをInstrumentsで追うためのcustom instrumentsやトレース・テンプレート(trace template)は,Haskell Platform 2011.2.0.1やGHC7.2.1では提供されていないので,自分でcustom instumentsを作るか,他のHaskellプログラマが作ったcustom instrumentsやテンプレートを利用する必要があります。

 Instrumentsを並列プロファイラとして利用するための取っ掛かりとしては,「More Fun Tracing Parallel Haskell Programs」という記事で提供されている「GHC HEC 2-core.tracetemplate」というテンプレートをダウンロードして改造するのがよいと思います。

 このテンプレートを使ってプロファイルを取ってみましょう。まず「GHC HEC 2-core.tracetemplate」をダブルクリックしてInstrumentsを起動します。「GHC HEC 2-core.tracetemplate」では,「dotp」というプログラムをデフォルトの「プロファイル対象のプロセス」としているため,Instruments起動時に「dotp」が「プロファイル対象のプロセス」としてドロップダウンリストに表示されます。「dotp」が表示されているこのドロップダウンリストをクリックし,「Chose Traget」→「Chose Target...」をクリックします。

Instruments1

 これにより,プロファイル対象のプロセスを指定するダイアログボックスが表示されます。ここで,Instrumentsで振る舞いを確かめたいプログラムを選びます。

Instruments2

 「Environment Variable」の項目で環境変数を指定して「Value」の項目で環境変数の値を設定したり,Argumentsの部分でプログラムに渡す引数を指定することもできます。ここでは引数として「+RTS -N」を渡しています。

Instruments3

 これらは後から指定することもできます。「プロファイル対象のプロセス」が表示されているドロップダウン・リストの中の「Edit Active Target」をクリックし,表示されたダイアログボックスで指定します。第43回のコラムで説明した-with-rtsopts=*オプションを使ってRTSオプションをプログラムに埋め込んでおけば,このような指定は不要です。

 Recordボタンをクリックして,Instrumentsを使ったプロファイルを実行してみましょう。プロファイルを実行した結果は以下の通りです。

Instruments4

 このように,Instrumentsを利用することで,EventLogの結果をThreadScopeで表示させる場合と同様に,DTraceを使って取得した情報をグラフィカルに表示できます。Gtk2Hsを利用するのが難しいMac OS X環境では,ThreadScopeの代わりにInstrumentsをグラフィカルな並列プロファイラとして利用するとよいでしょう。