テクニカルコラム かんたん♪ZFS
第十回:DTrace(2010年10月1日発行)

  こんにちは。今年の夏は記録的な暑さでしたが、お彼岸を過ぎ、ようやく
  涼しくなってきました。みなさんいかがお過ごしでしょうか。このコラム
  では実際に ZFS を使う上で役に立つ Tips を紹介します。

  今までのファイルシステムとは一味違う ZFS  を活用して面倒なファイル
  管理の苦労を減らしましょう!

 -------------------------------------------------------------------

  パフォーマンス改善を行う時、負荷に対して処理能力を持て余している部
  分を補強してもほとんど改善は望めません。一方、処理能力を目一杯使っ
  ている部分を補強すると、大きな改善を期待することができます。

  パフォーマンスを改善するには、処理状況をモニタし、システムの最も弱
  い部分を発見するのが、最初の一歩となります。前回は iostat、mpstat、
  vmstat を利用し、I/O、プロセッサ、メモリリソースの利用状況を確認す
  る方法を説明しました。今回は DTrace という機能について説明します。

   DTrace はサンマイクロシステムズが開発した、システムの動的なトレー
  スを行うための機能です。複雑な機能ですので、完全に使いこなすには、
  時間をかけてドキュメントを読む必要があります。しかし、典型的なプロ
  グラムを天下り的に使用して、ボトルネックの調査に役立てることもでき
  ます。

  まずは簡単な DTrace プログラムを紹介します。

      ----------------------------------------------------------
      #!/usr/sbin/dtrace -s

      #pragma D option quiet

      io:::start
      {
          @[args[1]->dev_statname] = quantize(args[0]->b_bcount);
      }
      ----------------------------------------------------------

  テキストエディタでこのプログラムが書かれたファイルを作成し、以下の
  ように実行してください (ファイル名を iosize.d) とします。

      # chmod 700 iosize.d
      # ./iosize.d
      ^C

        sd1
         value  ------------- Distribution ------------- count
          16 |                                         0
          32 |                                         2
          64 |                                         0
         128 |                                         0
         256 |                                         0
         512 |                                         34
        1024 |                                         42
        2048 |                                         41
        4096 |                                         17
        8192 |                                         10
       16384 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 53447
       32768 |                                         2
       65536 |                                         4
      131072 |                                         1
      262144 |                                         0


  自動的に終了しないので Ctrl + C を押して終了させます。

  このプログラムは、I/O ブロックサイズの統計情報を表示します。この例
  では 16384 [byte] = 16 [Kbyte] のアクセスが 53447 と表示されていま
  す。プログラム実行中に I/O 活動が無かった場合は何も表示されません。

  例えば、バックグラウンドでディスクを読み込むタスクを実行させてから、
  iosize.d を実行してみましょう。/dev/rdsk/c0t0d0p0 の部分は、お使い
  のシステムに合わせて変更してください。

      # dd if=/dev/rdsk/c0t0d0p0 of=/dev/null bs=32k &
      [1] 26713
      # ./iosize.d
      ^C

        sd1
         value  ------------- Distribution ------------- count
           256 |                                         0
           512 |                                         1
          1024 |                                         0
          2048 |                                         0
          4096 |                                         2
          8192 |                                         4
         16384 |                                         0
         32768 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 11214
         65536 |                                         0

  当然 32768 [byte] = 32 [Kbyte]  の読み込みが多くカウントされます。
  DTrace プログラムに戻って解説すると、io:::start の部分はプローブと
  呼ばれます。 プローブは provider:module:function:name という形式で
  表現されます。

      io:::start
      {
          @[args[1]->dev_statname] = quantize(args[0]->b_bcount);
      }

  このプログラムは io プロバイダの start  というプローブを使用して統
  計情報を取得します。このプローブについては『Solaris 動的トレースガ
  イド』において、次のように説明されています。

  「周辺機器 (デバイス) または NFS  サーバーに対する入出力要求が発行
    される直前に起動するプローブ。args[0] は、入出力要求の bufinfo_t
    をポイントしています。args[1] は、入出力要求の受け取り側デバイス
    の devinfo_t をポイントしています。 args[2] は入出力要求に対応す
    るファイルの fileinfo_t をポイントしています」

  bufinfo_t 構造体は次のように定義されています。

      typedef struct bufinfo {
          int        b_flags;      /* flags */
      >>> size_t     b_bcount;     /* number of bytes */
          caddr_t    b_addr;       /* buffer address */
          uint64_t   b_blkno;      /* expanded block # on device */
          uint64_t   b_lblkno;     /* block # on device */
          size_t     b_resid;      /* # of bytes not transferred */
          size_t     b_bufsize;    /* size of allocated buffer */
          caddr_t    b_iodone;     /* I/O completion routine */
          dev_t      b_edev;       /* extended device */
      } bufinfo_t;

  devinfo_t 構造体は次のように定義されています。

     typedef struct devinfo {
          int        dev_major;    /* major number */
          int        dev_minor;    /* minor number */
          int        dev_instance; /* instance number */
          string     dev_name;     /* name of device */
      >>> string     dev_statname; /* name of device
                                        + instance/minor */
          string     dev_pathname; /* pathname of device */
     } devinfo_t;

  これらはシステムの I/O 入出力関数に渡された引数です。io:::start プ
  ローブを使うとこららのパラメータを参照することができます。
  @[] = quantize() は集積体とよばれ、 指定された式の二乗分布を作成し
  ます。 集積関数には quantize() 以外にも、 count() - 呼び出された回
  数、sum() - 指定された式の合計、などがあります。

  サンプルプログラムでは、 args[0]->b_bcount (ブロックサイズ) の二乗
  分布を args[1]->dev_statname (デバイス名) 毎に集計します。

     @[args[1]->dev_statname] = quantize(args[0]->b_bcount);

  このように、プローブがどのような契機で、どのような値を取得すること
  ができるのかを知っていれば、 iostat や mpstat よりも実際の処理と密
  接に結びついた情報を得ることができます。

  今回は DTrace の基本的な部分を紹介させていただきました。次回も引き
  続き、いつくかの DTrace サンプルプログラムを使用した、システム情報
  の収集方法について紹介します。

  (つづく)


  ■ 参考文献

   (1) サンマイクロシステムズ、"SunOS リファレンスマニュアル 1 :
        ユーザコマンド"、Part No. 819-1210-13、2007 年 7 月

   (2) サンマイクロシステムズ、"SunOS リファレンスマニュアル 1M :
        システム管理コマンド"、Part No. 819-1211-13、2007 年 7 月

    (3) サンマイクロシステムズ、"Solaris 動的トレースガイド", 
        Part No. 819-0395-12、2008 年 10 月

    (4) サンマイクロシステムズ、"Dtrace ユーザガイド", Part No.
        819-6259-10、2006 年 5 月
 
 (高田 浩生)
世界最高峰の技術で、世界最高性能のストレージを
Copyright 2020 Core Micro Systems Inc., All rights reserved.