#chiroito ’s blog

Java を中心とした趣味の技術について

Oracle Linux で Dtrace を使う

性能分析をしていると、OS上で稼働しているプロセスがそれぞれどのくらいのデータ長を何回書いたのか、Java のスレッドのライフサイクルを測定したいということは無いでしょうか。ですが、これらの情報を取得することはアプリケーションを対応させたりなどしないといけないため大変です。DTrace を使用するとカーネルが対応していればカーネルの情報を簡単に取得できるようになり、Javaが対応してればJavaの情報を簡単に取得できるようになります。

DTraceでは情報を取得するポイントをプローブと言い、プローブの単位でどの様な情報を取得するかを指摘できます。プローブにはディスクの読み書き、Javaのスレッドのライフサイクルやクラスローディングなどがあります。

今回は、Oracle Linux 7.3 UEK 4 の環境に DTrace をインストールします。

> cat /etc/oracle-release
Oracle Linux Server release 7.3
> uname -r
4.1.12-61.1.19.el7uek.x86_64

Dtrace をインストール

以下のサイトから dtrace-utils をダウンロードします。
Oracle Linux DTrace

今回は次のバージョンのものをダウンロードします。

DTrace utilities for development with Unbreakable Enterprise Kernel R4
DTrace utilities, Oracle Linux 7 (x86_64)

ダウンロードが終わったら root ユーザでインストールしましょう。依存関係のあるパッケージがあるため、yumでインストールします。

> yum localinstall dtrace-utils-*.rpm
(略)
インストール:
  dtrace-utils.x86_64 0:0.5.1-3.el7

依存性関連をインストールしました:
  dtrace-modules-shared-headers.x86_64 0:0.5.3-2.el7    libdtrace-ctf.x86_64 0:0.5.0-3.el7

完了しました!

測定ポイントのロード

DTrace を使うには測定のポイントとなるプローブ(Probe)が必要となります。インストールして直ぐは DTrace 自体のプローブのみがロードされていて測定したいもののプローブはロードされていません。

dtrace に -l オプションを付けるとロードされているプローブを一覧表示します。

> /usr/sbin/dtrace -l
Downloading DTrace module...
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR

プローブはdtraceのものしか読まれていなかったので、systraceprofileのプローブをロードしましょう。

> modprobe systrace
> modprobe profile

もう一度、dtrace -lするとsystraceprofileのプローブがロードされているのが確認できます。

> /usr/sbin/dtrace -l
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR
    4    syscall           vmlinux                              read entry
    5    syscall           vmlinux                              read return

試しに情報取得

稼働しているプロセスがどのくらいのデータ長を何回書いたかを取得してみます。DTrace の詳細は割愛しますが、この結果では、プロセス名、データ長、書込回数、の順で出力されます。実行してからctrl+cを押すまでの間、情報を収集し、その収集結果を出力します。

> /usr/sbin/dtrace -n 'syscall::write:entry /execname != NULL/ { @writes[execname, arg2] = count(); }'
dtrace: description 'syscall::write:entry ' matched 1 probe
^C

  agent                                                             6                1
  agent                                                            99                1
  agent                                                          2115                1
  docker-proxy                                                      2                1
  docker-proxy                                                      6                1
  dockerd                                                           7                1
  dockerd                                                        4096                1
  dockerd                                                       18312                1
  dtrace                                                            1                1
  healthcheck                                                      10                1

ZFS on Linux の設定値の場所

ZFS の値を調べるときにいつも場所を忘れてしまうためのメモ。

インストールしている ZFS on Linux のバージョンは次の通り 0.6.5.8 です。

> rpm -qa | grep zfs
libzfs2-0.6.5.8-1.el7.centos.x86_64
zfs-release-1-3.el7.centos.noarch
zfs-0.6.5.8-1.el7.centos.x86_64
zfs-dkms-0.6.5.8-1.el7.centos.noarch

場所は /sys/module/zfs/parameters/ です。設定できる項目は次のようになっています。

> ls /sys/module/zfs/parameters/
ignore_hole_birth                      zfs_arc_p_dampener_disable            zfs_scan_idle
l2arc_feed_again                       zfs_arc_p_min_shift                   zfs_scan_min_time_ms
l2arc_feed_min_ms                      zfs_arc_shrink_shift                  zfs_scrub_delay
l2arc_feed_secs                        zfs_arc_sys_free                      zfs_send_corrupt_data
l2arc_headroom                         zfs_autoimport_disable                zfs_sync_pass_deferred_free
l2arc_headroom_boost                   zfs_dbgmsg_enable                     zfs_sync_pass_dont_compress
l2arc_nocompress                       zfs_dbgmsg_maxsize                    zfs_sync_pass_rewrite
l2arc_noprefetch                       zfs_dbuf_state_index                  zfs_top_maxinflight
l2arc_norw                             zfs_deadman_enabled                   zfs_txg_history
l2arc_write_boost                      zfs_deadman_synctime_ms               zfs_txg_timeout
l2arc_write_max                        zfs_dedup_prefetch                    zfs_vdev_aggregation_limit
metaslab_aliquot                       zfs_delay_min_dirty_percent           zfs_vdev_async_read_max_active
metaslab_bias_enabled                  zfs_delay_scale                       zfs_vdev_async_read_min_active
metaslab_debug_load                    zfs_dirty_data_max                    zfs_vdev_async_write_active_max_dirty_percent
metaslab_debug_unload                  zfs_dirty_data_max_max                zfs_vdev_async_write_active_min_dirty_percent
metaslab_fragmentation_factor_enabled  zfs_dirty_data_max_max_percent        zfs_vdev_async_write_max_active
metaslab_lba_weighting_enabled         zfs_dirty_data_max_percent            zfs_vdev_async_write_min_active
metaslab_preload_enabled               zfs_dirty_data_sync                   zfs_vdev_cache_bshift
metaslabs_per_vdev                     zfs_disable_dup_eviction              zfs_vdev_cache_max
spa_asize_inflation                    zfs_expire_snapshot                   zfs_vdev_cache_size
spa_config_path                        zfs_flags                             zfs_vdev_max_active
spa_load_verify_data                   zfs_free_leak_on_eio                  zfs_vdev_mirror_switch_us
spa_load_verify_maxinflight            zfs_free_max_blocks                   zfs_vdev_read_gap_limit
spa_load_verify_metadata               zfs_free_min_time_ms                  zfs_vdev_scheduler
spa_slop_shift                         zfs_immediate_write_sz                zfs_vdev_scrub_max_active
zfetch_array_rd_sz                     zfs_max_recordsize                    zfs_vdev_scrub_min_active
zfetch_block_cap                       zfs_mdcomp_disable                    zfs_vdev_sync_read_max_active
zfetch_max_streams                     zfs_metaslab_fragmentation_threshold  zfs_vdev_sync_read_min_active
zfetch_min_sec_reap                    zfs_mg_fragmentation_threshold        zfs_vdev_sync_write_max_active
zfs_admin_snapshot                     zfs_mg_noalloc_threshold              zfs_vdev_sync_write_min_active
zfs_arc_average_blocksize              zfs_no_scrub_io                       zfs_vdev_write_gap_limit
zfs_arc_grow_retry                     zfs_no_scrub_prefetch                 zfs_zevent_cols
zfs_arc_lotsfree_percent               zfs_nocacheflush                      zfs_zevent_console
zfs_arc_max                            zfs_nopwrite_enabled                  zfs_zevent_len_max
zfs_arc_meta_adjust_restarts           zfs_object_mutex_size                 zil_replay_disable
zfs_arc_meta_limit                     zfs_pd_bytes_max                      zil_slog_limit
zfs_arc_meta_min                       zfs_prefetch_disable                  zio_delay_max
zfs_arc_meta_prune                     zfs_read_chunk_size                   zio_requeue_io_start_cut_in_line
zfs_arc_meta_strategy                  zfs_read_history                      zio_taskq_batch_pct
zfs_arc_min                            zfs_read_history_hits                 zvol_inhibit_dev
zfs_arc_min_prefetch_lifespan          zfs_recover                           zvol_major
zfs_arc_num_sublists_per_state         zfs_resilver_delay                    zvol_max_discard_blocks
zfs_arc_p_aggressive_disable           zfs_resilver_min_time_ms              zvol_prefetch_bytes

catコマンドなどで中身を見ることができます。

> cat zfs_dirty_data_max
3340944179

Docker Compose で Oracle Database を動かす

Docker 上で Oracle Database のイメージが構築されているものとします。まだ、Docker 上で Oracle Database を構築していない場合にはこちらをご参照ください。

公式 Oracle Database の Docker イメージを構築 - @chiroito ’s blog

docker コマンドを使用して Oracle Database を動かすには以下の様に引数を並べて起動します。

> docker run --name orcl -p 1521:1521 -p 5500:5500 -v /mnt/oradata:/opt/oracle/oradata \
> -e ORACLE_SID=orcl -e ORACLE_PDB=pdb1 oracle/database:12.1.0.2-ee

実際に環境を使う場合にはデータベースだけを起動してシステムを構築することは無く、アプリケーションサーバなども同時に起動します。

上の dockerコマンドで起動している内容と同じ内容を docker-compose.ymlファイルに設定し Docker Compose を使用して起動しましょう。

コンテナデータベースの名前に相当する環境変数は ORACLE_SID、プラガブルデータベースの名前に相当する環境変数は ORACLE_PDB です。データベースへ接続するポートは 1521 、管理ツールへアクセスするポートは 5500 です。また、データベースのデータはコンテナの /opt/oracle/oradata に格納されます。

docker-compose.yml

orcl:
  image: oracle/database:12.1.0.2-ee
  volumes:
    - /mnt/oradata:/opt/oracle/oradata
  ports:
    - "1521:1521"
    - "5500:5500"
  environment:
    ORACLE_SID: orcl
    ORACLE_PDB: pdb1

docker-compose.ymlファイルを作成したら、ファイルのあるディレクトリで以下の様に実行すると Oracle Database が起動します。

docker-compose up