more dtrace

先週の事だけど、春の陽気に誘われて税務署へ確定申告に行ってきた。別にFXで大儲けした訳 でもないので、そこん所誤解なきように。って、誤解する人も居ないよね。

この確定申告は、2/15からなんだけど、それ以前にも出来るようだ。期日前に申告したものは 税務署預かりになるとか。わざわざ税務署に出向かなくても、ブラウザーを使って家からも 出来ますよと、酷税庁のHPではさんざん宣伝してる。

でも、ネットでやろうとすると、悪名高き住基カードであらかじめ登録しておいてカード リーダーが必要。それがいやなら、家のプリンターに書類を打ち出してから郵送せいという 事になる。プリンターに打ち出す時に、PDFに変換するようなのだけど、アドビのやつしか 使えないようだ。おいらこの点で萎えましたよ。だって、アドビ製は、重い、でかい、メンテが 大変と3拍子揃ってますから、PCには入れていないんだ。この為だけにインストールするっての も、いやなんで断念したんだ。大体、PDFリーダーにJavaScriptをサポートする必要なんて あるんかいだ。国が執り行う事業なのにアドビ指定とは、いかがなものかと思うぞ。

我等がしもべである税務署職員がちゃんと働いているかの視察も兼ねて、午後1時ぴったりに 税務署へ行きましたよ。そしたら、丁度受付が始まった所でした。申告内容によって3種類に 分類してました。おいらが投入されたQueueは、前に2人並んでました。この時点で、Load averageが 2ですか。よく見てると、Queueによって進行スピードが違います。文句を言ってる人も いましたよ。

ほどなくして、おいらの番がきました。まずは、英数字8文字以上のパスワードを登録して ください、ですって。急に言われても、そんなの出てこんよ。ちょいと考えこんでいたら、 みなさん、生年月日とイニシャルを組み合わせてますよ、だってさ。おいおい、そんな誘導 するなよ。セキュリティーに対するリテラシーがゼロだぜ。こんなんじゃだめだろうに。

それが済んだら、基本情報やら、個別情報を入力して終わり。あっけないぐらい簡単に 終了しました。

帰りしなQueueを確認したら、ロードアベレージが30ぐらいになってました。中には 腰の曲がった、おじいちゃん、おばあちゃんも混じってます。かわいそうに、ずっと 立たされたままなんですかね。せめて椅子を用意してあげる等の気配りは出来んのかね。 金を返してやるんだから、少しぐらいは我慢しろと言ってるようで腹が立ちましたよ。

more dtrace

昔、fortless とか言う過激な名前の言語をSunの人が作ってました。何故過激? 私の推測ですが、fortran lessから来てると思うんだ。fortranより覚える事が 少なくて済む、やさしい言語って事でしょうか。

だったら、

Javaless ==> ruby

とかでしょうね。

more dtraceなら、いいでしょうか。もう少し dtraceのtoolKitを冒険してみます。 えっと、前回は、dtraceとrubyのコラボーションを見ましたが、いろいろな言語で dtrace出来るように、世界の好き者が頑張っています。

sakae@solaris:/opt/DTT/Code$ ls
C  Java  JavaScript  Perl  Php  Python  Readme  Ruby  Shell  Tcl

いろいろありますねぇ。JavaScriptにまであるって、ちょっとびっくりです。 そんじゃ、試してみますかね。

jruby は、どうかな?

jrubyって、dtrace上は、rubyの仲間? それともjava派?

ruby族かと思って試してみたら、dtraceしてくれんかった。jrubyって皮を被って ますね。

sakae@solaris:~/DTRACE$ file /usr/bin/jruby
/usr/bin/jruby: 実行可能 /bin/bash スクリプト

皮を調べてみたら、cygwinでも起動出来るようになってたよ。MS世界への侵略作戦だな。 Javaのオプションを渡せるように、Jオプションも用意してるあたり、用意周到だな。

sakae@solaris:~/DTRACE$ jruby -J
Usage: java [-options] class [args...]
           (to execute a class)
   or  java [-options] -jar jarfile [args...]
           (to execute a jar file)

where options include:
    -d32          use a 32-bit data model if available

    -d64          use a 64-bit data model if available
    -client       to select the "client" VM
    -server       to select the "server" VM
    -hotspot      is a synonym for the "client" VM  [deprecated]
                  The default VM is client.
                     :

これを見てて思い出したんだけど、clojureを起動する時、-server オプションを 付けると、劇的に実行スピードが上がるとか。

そんじゃ、jrubyをJava族としてdtraceしてみます。Java用のdtraceスクリプトも いろいろ用意されてます。どんなのがあるかと言うと

Readme        j_classflow.d  j_flow.d         j_package.d   j_syscolors.d
j_calldist.d  j_cpudist.d    j_flowtime.d     j_profile.d   j_thread.d
j_calls.d     j_cputime.d    j_methodcalls.d  j_stat.d      j_who.d
j_calltime.d  j_events.d     j_objnew.d       j_syscalls.d
sakae@solaris:/opt/DTT/Java$ lv j_package.d
#!/usr/sbin/dtrace -Zs
/*
 * j_package.d - count Java class loads by package using DTrace.
 *               Written for the Java hotspot DTrace provider.
*/
     :

こんなのを選んでみました。Java用のdtraceを有効にするには、被測定javaプログラムに オプションを渡す必要があります。さて、行ってみよー。

sakae@solaris:~/DTRACE$ jruby -J-XX:+ExtendedDTraceProbes func_slow.rb
Function A
Function B
Function C

実行結果は

sakae@solaris:/opt/DTT/Java$ pfexec ./j_package.d
Tracing... Hit Ctrl-C to end.
^C
      PID    LOADS  PACKAGE
    15981        1  com/sun/jmx/remote/util
    15981        1  java/awt
      :
    15981       53  sun/misc
    15981       59  org/jruby/gen
    15981       99  java/lang
    15981      115  java/util
    15981     1233  org/jruby

次は、j_objnew.dの結果です。

    :
    16003  [C
           value  ------------- Distribution ------------- count
               8 |                                         0
              16 |@@@@@                                    2387
              32 |@@@@@@@@@@@@@@@@@                        7877
              64 |@@@@@@@@@@@@@@                           6428
             128 |@@@@                                     1644
             256 |@                                        267
             512 |                                         39
            1024 |                                         6
            2048 |                                         8
            4096 |                                         1
            8192 |                                         2
           16384 |                                         5
           32768 |                                         1
           65536 |                                         0

    16003  org/jruby/RubyFixnum
           value  ------------- Distribution ------------- count
              16 |                                         0
              32 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 1199516
              64 |                                         0

Java object allocation count by pid and class,

    PID     OBJS CLASS
  16003        1 $Proxy0
  16003        1 [Ljava/lang/Integer;
     :
  16003     4390 java/util/HashMap$Entry
  16003     6073 [B
  16003    13782 java/lang/String
  16003    18665 [C
  16003  1199516 org/jruby/RubyFixnum

にやにやするには、うってつけ?

もう一丁行きます。今度は、clojureを起動してプロンプトが出てくるまでの、慌しさを モニターします。

sakae@solaris:~/clojure-1.1.0$ java -XX:+ExtendedDTraceProbes -cp clojure.jar clojure.main
Clojure 1.1.0
user=>

やっぱり、舞台裏は忙しかったね。ごみ集めまでしてるよ。

sakae@solaris:/opt/DTT/Java$ pfexec ./j_stat.d
TIME                 EXEC/s THREAD/s METHOD/s OBJNEW/s  CLOAD/s EXCP/s   GC/s
2010 Feb 28 16:09:18      0        0        0        0        0      0      0
2010 Feb 28 16:09:19      0        0        0        0        0      0      0
2010 Feb 28 16:09:20      2        5    18697     5488      303     40      0
2010 Feb 28 16:09:21      0        0   139572    22921      283    109      2
2010 Feb 28 16:09:22      0        0   175598    31764      166    160      2
2010 Feb 28 16:09:23      0        0   145002    28572      251    251      3
2010 Feb 28 16:09:24      0        0   169840    28890      230    216      2
2010 Feb 28 16:09:25      0        0   201867    31037       95     94      2
2010 Feb 28 16:09:26      0        0   228842    36332       45     36      2
2010 Feb 28 16:09:27      0        0   162605    28748      132     48      2
2010 Feb 28 16:09:28      0        0        0        0        0      0      0
sakae@solaris:/opt/DTT/Java$ pfexec ./j_cputime.d
Tracing... Hit Ctrl-C to end.
^C

Top 10 counts,
      PID TYPE       NAME                                                COUNT
    16096 method     clojure/lang/PersistentHashMap$BitmapIndexedNode.find    18033
    16096 method     java/lang/String.startsWith                         19501
    16096 method     java/lang/Object.equals                             22987
    16096 method     clojure/lang/PersistentHashMap.valAt                28667
    16096 method     java/lang/Object.<init>                             32641
    16096 method     clojure/lang/Var.get                                34344
    16096 method     java/lang/Integer.bitCount                          38850
    16096 method     clojure/lang/Var.deref                              43969
    16096 method     clojure/lang/Var.getThreadBinding                   43980
        0 total      -                                                 1251112

Top 10 on-CPU times (us),
      PID TYPE       NAME                                                TOTAL
    16096 gc         GC                                                 104117

Top 10 exclusive method on-CPU times (us),
      PID TYPE       NAME                                                TOTAL
    16096 method     clojure/lang/Var.getThreadBinding                  189635
    16096 method     clojure/lang/PersistentHashMap$BitmapIndexedNode.find   209275
    16096 method     clojure/core$refer__5598.doInvoke                  217686
    16096 method     java/lang/ClassLoader.defineClass1                 219943
    16096 method     clojure/core$filter_key__5559.invoke               243346
    16096 method     clojure/lang/PersistentHashMap.valAt               251209
    16096 method     clojure/lang/Var.get                               285749
    16096 method     clojure/lang/PersistentHashMap$BitmapIndexedNode.assoc   295069
    16096 method     clojure/lang/Var.deref                             367520
        0 total      -                                                12770646

Top 10 inclusive method on-CPU times (us),
      PID TYPE       NAME                                                TOTAL
    16096 method     clojure/core__init.<clinit>                       5794047
    16096 method     clojure/lang/RestFn.invoke                        7358242
    16096 method     clojure/lang/RT.doInit                           10464696
    16096 method     java/lang/ClassLoader.loadClass                  10800377
    16096 method     clojure/lang/RT.loadClassForName                 10899812
    16096 method     clojure/lang/RT.<clinit>                         10969485
    16096 method     java/lang/Class.forName0                         11013430
    16096 method     java/lang/Class.forName                          11023724
    16096 method     clojure/main.<clinit>                            11135560
    16096 method     clojure/lang/RT.load                             20094494

きりがないので、これぐらいにしといたる。 そうそう、Java屋さんには、dtraceのJava版であるbtraceの方が馴染みがあって、良いかも 知れません。D言語の代わりにjavaで書けるみたい。だったら、絶対にコマンド名は jtraceだと思うんだけど、JDKの中にある、J接頭語とぶつかるのを避けるために、頭が bなんだそうです。そして、bはこじつけがましく、byte code から頂いてきたとか。

次は、えーーと、、

FreeBSDでもdtraceする

Netを検索してみると、FreeBSD 7.1から、dtraceがサポートされたようだ。でも、こう いう機能は誰でも使うわけではないので、常にenableになってはいない。 使うためには、kernelを再構築してから再起動し、モジュールをロードすると言う手順が 必要みたい。好き者用だな。そんじゃ、やってみんべぇー。

options KDTRACE_HOOKS        # all architectures
#options KDTRACE_FRAME        # amd64-only

上記を追加する。FreeBSD 8.0では、KDTRACE_HOOKSはコメントになってた。

$ cd /usr/obj/usr/src/sys/GENERIC/
$ make clean
$ cd /usr/src
$ make buildkernel WITH_CTF=1
$ make installkernel

WITH_CTF=1が肝らしい。これを忘れると、ロード時にエラーになるとか。何だろうと思って 探ってみると、Makefile.inc1に

#       -DNO_CTF do not run the DTrace CTF conversion tools on built objects

こんな記述が見つかった。察してあげる事にします。 私の仮想PCでは、コンパイルに30分かかった。マシンが速くなるのと、コンパイル負荷が 増大するのと何時も追いかけっこしてて、時間短縮は出来ないなあ、と、天を仰ぐのでした。 新しいkernelで再起動してから、モジュールをロードします。

[sakae@cdr ~]$ sudo kldload dtraceall
[sakae@cdr ~]$ kldstat
Id Refs Address    Size     Name
 1   37 0xc0400000 c5e710   kernel
 2    2 0xc105f000 567d0    sound.ko
 3    1 0xc10b6000 8c44     snd_es137x.ko
 4    1 0xc10bf000 4e7c     vmxnet.ko
 5    1 0xc3405000 2000     star_saver.ko
 6    1 0xc3424000 4000     vmmemctl.ko
 7    1 0xc354c000 2000     dtraceall.ko
 8    1 0xc354e000 3000     profile.ko
 9   10 0xc3552000 3000     opensolaris.ko
10    3 0xc3555000 4000     cyclic.ko
11    8 0xc355a000 137000   dtrace.ko
12    1 0xc3716000 f000     systrace.ko
13    1 0xc3725000 2000     sdt.ko
14    1 0xc3727000 2000     lockstat.ko
15    1 0xc3735000 4000     fbt.ko
16    1 0xc3759000 3000     dtnfsclient.ko
17    1 0xc375c000 2000     dtmalloc.ko

dtrace関係は、Idが7以降のものです。なんともろにopensolarisなんてモジュールも ロードされてます。そんじゃ、幾つプローブが有るか調べてみます。

[sakae@cdr ~]$ sudo dtrace -l | wc -l
   40022

opensolarisでは、6万個ありましたから、FreeBSDは大分少ないですね。人材が不足してて 設置が進まないのでしょうか? プローブ設置し隊に立候補し鯛ぞ。

dtraceToolKitを、FreeBSDにも持ってきました。installと言うもろな名前のインストーラ が付属してます。が、スクリプトがksh語で書かれていたので、所定の場所に収めるのは 諦めました。適当に潜って、実験してみます。

[root@cdr /usr/home/sakae/DTraceToolkit-0.99/Kernel]# ./modcalls.d
dtrace: script './modcalls.d' matched 19104 probes
^C

  opensolaris                                                      10
  vmmemctl                                                       6948
  star_saver                                                    46785
  kernel                                                     46823481

スクリプトを起動して暫く放置しておきました。そして止めてみました。どうやら、 カーネルモジュールの呼び出し回数をカウントしてたようです。star_saverってのは、コンソール 用のスクリーンセーバーです。(お星様が、キラキラします)結構な回数、呼ばれているの ちょっとびっくりです。

[root@cdr /usr/home/sakae/DTraceToolkit-0.99/Proc]# ./syscallbyproc.d
dtrace: script './syscallbyproc.d' matched 505 probes
^C

  syslogd                                                          38
  env                                                              40
  which                                                            50
  rm                                                               52
  grep                                                             92
  id                                                              124
  bash                                                            125
  uname                                                           141
  mkdir                                                           143
  expr                                                            192
  touch                                                           196
  awk                                                             213
  patch                                                           275
  sed                                                             335
  sudo                                                            616
  true                                                            684
  md5                                                             784
  sha256                                                          784
  chmod                                                           790
  chown                                                           867
  gmake                                                          1104
  make                                                           1186
  dtrace                                                         2752
  sh                                                             3073
  unzip                                                          5333
  vmtoolsd                                                       8246
  cc                                                            16172
  screen                                                        16551
  sshd                                                          20066
  ld                                                            27030
  as                                                            28159
  cc1                                                          154206

これは、裏でとあるportsをコンパイルしてた時の、プロセス(コマンド)毎の システムコール状況です。portsのコンパイルとは言え、いろいろなコマンドが 駆使されてますねえ。

[root@cdr /usr/home/sakae/DTraceToolkit-0.99/Proc]# ./pidpersec.d
dtrace: failed to compile script ./pidpersec.d: line 48: probe description proc:::exec-suc

一方、FreeBSDには、まだ移植されていないプローブもあり、そういうのは、dtrace自身 が失敗に終わってしまいます。グスン。

で、FreeBSDでも動きそうなプローブを使って、何か作ってみます。超簡単なやつで、へぇー と面白そうなもの、

#!/usr/sbin/dtrace -s

syscall::exec*:entry { @num[execname] = count(); }

このD言語は、コマンドの呼び出し回数をカウントするものです。これを使って、ruby 1.8.6(with dtrace) をインストールする過程で発行されるコマンドを調べてみました。なお、FreeBSD8.0では 、何故かext/opensslのコンパイルに失敗するので、あらかじめ除外してます。

==== configure ====
  make                                                              1
  groff                                                             2
  cc                                                                3
  gcc                                                             527
  sh                                                             2723
==== make ====
  sh                                                                7
  miniruby                                                         33
  gcc                                                             192
  make                                                            791
==== make test ====
  make                                                              1
  miniruby                                                          1
  sh                                                                2
  ruby                                                              8
==== make install ====
  sh                                                                1
  make                                                              7

(私の常用shellであるbashがそれぞれ1回カウントされてましたが、結果からは除外しています)

configureで思いの他、gccが呼び出されているのには、ちょいとびっくりしましただ。 また、minirubyがけなげに活躍してますね。(親の)rubyが出来ちゃうと、ポィって 捨てられちゃう不憫な子なんですけどね。

こうして出来たdtrace入りrubyですが、FreeBSDでは残念ながらdtraceしてくれませんでした。 また、javaもdtraceしてくれませんでした。移植版と言ってもopensolaris のように、すらすらとはいかないんですね。

それじゃ最後に、FreeBSDでのdtrace関係者にお集まり頂きます。但し、都合により/sys 以下だけにしますね。

[sakae@cdr /sys]$ find . -name '*.c' | xargs grep -l DTRACE
./amd64/amd64/local_apic.c
./amd64/amd64/trap.c
./cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
./cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c
./cddl/contrib/opensolaris/uts/common/dtrace/lockstat.c
./cddl/contrib/opensolaris/uts/common/dtrace/profile.c
./cddl/contrib/opensolaris/uts/common/dtrace/sdt_subr.c
./cddl/contrib/opensolaris/uts/common/dtrace/systrace.c
./cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
./cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
./cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
./cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
./cddl/dev/prototype.c
./cddl/dev/dtmalloc/dtmalloc.c
./cddl/dev/dtrace/dtrace_debug.c
./cddl/dev/dtrace/dtrace_ioctl.c
./cddl/dev/dtrace/dtrace_load.c
./cddl/dev/dtrace/dtrace_vtime.c
./cddl/dev/dtrace/amd64/dtrace_isa.c
./cddl/dev/dtrace/amd64/dtrace_subr.c
./cddl/dev/dtrace/i386/dtrace_isa.c
./cddl/dev/dtrace/i386/dtrace_subr.c
./cddl/dev/fbt/fbt.c
./cddl/dev/lockstat/lockstat.c
./cddl/dev/profile/profile.c
./cddl/dev/sdt/sdt.c
./cddl/dev/systrace/systrace.c
./contrib/ngatm/netnatm/msg/privmsg.c
./i386/i386/local_apic.c
./i386/i386/trap.c
./i386/isa/clock.c
./kern/kern_dtrace.c
./kern/kern_exec.c
./kern/kern_exit.c
./kern/kern_fork.c
./kern/kern_lock.c
./kern/kern_lockstat.c
./kern/kern_malloc.c
./kern/kern_mutex.c
./kern/kern_rmlock.c
./kern/kern_rwlock.c
./kern/kern_sdt.c
./kern/kern_sx.c
./kern/sched_4bsd.c
./kern/sched_ule.c
./kern/vfs_cache.c
./nfsclient/nfs_bio.c
./nfsclient/nfs_kdtrace.c
./nfsclient/nfs_krpc.c
./nfsclient/nfs_subs.c
./nfsclient/nfs_vnops.c
./pc98/cbus/clock.c

あれ、FreeBSDって、sparc等もサポートしてるんですが、まだ移植されて いないですね。誰か、sparcな石が入ったワークステーションを寄付して ください。そしたら、移植するよ。