アロケーションプロファイリング
ClickHouse はグローバルアロケータとして jemalloc を使用しています。jemalloc には、アロケーションのサンプリングおよびプロファイリング用のツールが付属しています。
アロケーションプロファイリングをより手軽に行えるように、ClickHouse と Keeper では、設定ファイルやクエリ設定、SYSTEM コマンド、Keeper の four letter word (4LW) コマンドを使用してサンプリングを制御できます。
さらに、サンプルは JemallocSample 型として system.trace_log テーブルに収集できます。
このガイドはバージョン 25.9 以降に適用されます。
それ以前のバージョンについては、25.9 より前のバージョン向けアロケーションプロファイリング を参照してください。
アロケーションのサンプリング
jemalloc でアロケーションのサンプリングおよびプロファイリングを行うには、jemalloc_enable_global_profiler 設定を有効にして ClickHouse/Keeper を起動する必要があります。
jemalloc はアロケーションをサンプリングし、その情報を内部に保持します。
jemalloc_enable_profiler 設定を使用することで、クエリ単位のアロケーションを有効にすることもできます。
ClickHouse はアロケーションが多いアプリケーションであるため、jemalloc のサンプリングによりパフォーマンス上のオーバーヘッドが発生する可能性があります。
system.trace_log に jemalloc サンプルを保存する
すべての jemalloc サンプルを JemallocSample 型として system.trace_log に格納できます。
これをグローバルに有効化するには、設定項目 jemalloc_collect_global_profile_samples_in_trace_log を使用します。
ClickHouse はメモリ割り当てを多用するアプリケーションであるため、system.trace_log ですべてのサンプルを収集すると高負荷になる可能性があります。
jemalloc_collect_profile_samples_in_trace_log 設定を使用して、クエリごとに有効化することもできます。
system.trace_log を使用してクエリのメモリ使用量を分析する例
まず、jemalloc プロファイラを有効にしてクエリを実行し、そのクエリのサンプルを system.trace_log に収集する必要があります。
ClickHouse を jemalloc_enable_global_profiler を有効にして起動した場合、jemalloc_enable_profiler を有効にする必要はありません。
jemalloc_collect_global_profile_samples_in_trace_log と jemalloc_collect_profile_samples_in_trace_log についても同様です。
ここで system.trace_log をフラッシュします。
そして、それに対してクエリを実行し、各時点で実行したクエリのメモリ使用量を取得します。
メモリ使用量が最大だった時刻も確認できます:
その結果を使って、その時点でどこからの割り当てが最も活発だったかを確認できます。
ヒーププロファイルのフラッシュ
デフォルトでは、ヒーププロファイル用ファイルは /tmp/jemalloc_clickhouse._pid_._seqnum_.heap に生成されます。ここで _pid_ は ClickHouse の PID、_seqnum_ は現在のヒーププロファイルに対応するグローバルなシーケンス番号です。
Keeper のデフォルトファイルは /tmp/jemalloc_keeper._pid_._seqnum_.heap で、同じルールに従います。
jemalloc に現在のプロファイルをフラッシュさせるには、次を実行します。
- ClickHouse
- Keeper
フラッシュされたプロファイルの保存先パスが返されます。
MALLOC_CONF 環境変数に prof_prefix オプションを追加することで、別の保存場所を指定できます。
例えば、/data ディレクトリ内に、ファイル名のプレフィックスを my_current_profile としてプロファイルを生成したい場合は、次の環境変数を指定して ClickHouse/Keeper を実行します。
生成されるファイル名は、プレフィックスに PID とシーケンス番号を連結したものになります。
ヒーププロファイルの分析
ヒーププロファイルが生成されたら、それらを分析する必要があります。
そのために、jemalloc のツールである jeprof を使用できます。次のいずれかの方法でインストールできます。
- システムのパッケージマネージャーを使用する
- jemalloc リポジトリをクローンし、ルートディレクトリで
autogen.shを実行する。これにより、binディレクトリ内にjeprofスクリプトが作成されます
jeprof を使用して、ヒーププロファイルからさまざまな形式を生成できます。
ツールの使い方や提供される各種オプションについては、jeprof --help を実行して確認できます。
シンボル情報付きヒーププロファイル
バージョン 26.1 以降では、SYSTEM JEMALLOC FLUSH PROFILE を使用してフラッシュを実行すると、ClickHouse は自動的にシンボル情報付きのヒーププロファイルを生成します。
シンボル情報付きプロファイル(拡張子は .symbolized)には関数シンボルが埋め込まれており、ClickHouse のバイナリを用意しなくても jeprof で分析できます。
たとえば、次のように実行すると:
ClickHouse は、シンボル化されたプロファイルへのパスを返します(例: /tmp/jemalloc_clickhouse.12345.0.heap.symbolized)。
その後、これを jeprof で直接解析できます。
バイナリは不要です: シンボル化されたプロファイル(.symbolized ファイル)を使用する場合、jeprof に ClickHouse バイナリのパスを指定する必要はありません。これにより、別のマシン上で、あるいはバイナリを更新した後でも、プロファイルをはるかに簡単に分析できるようになります。
古いシンボル化されていないヒーププロファイルがあり、引き続き ClickHouse バイナリにアクセスできる場合は、従来の方法を使用できます。
シンボル化されていないプロファイルの場合、jeprof はスタックトレースを生成するために addr2line を使用しますが、処理が非常に遅くなることがあります。
その場合は、このツールの代替実装をインストールすることを推奨します。
また、llvm-addr2line も同様に問題なく動作します(ただし、llvm-objdump は jeprof とは互換性がない点に注意してください)。
その後、次のように指定して使用します: jeprof --tools addr2line:/usr/bin/llvm-addr2line,nm:/usr/bin/llvm-nm,objdump:/usr/bin/objdump,c++filt:/usr/bin/llvm-cxxfilt
:::
2つのプロファイルを比較する際には、--base 引数を使用できます。
例
シンボル化されたプロファイルを使用する(推奨):
- 各プロシージャを 1 行に 1 つずつ記載したテキストファイルを生成します:
- コールグラフを含む PDF ファイルを生成する:
シンボル化されていないプロファイルを使用する場合(バイナリが必要):
- 各関数を 1 行ずつ記述したテキストファイルを生成します。
- コールグラフを含む PDF ファイルを生成する:
フレームグラフの生成
jeprof を使用すると、フレームグラフの作成に必要なコラプスされたスタック(collapsed stacks)を生成できます。
--collapsed 引数を使用する必要があります。
あるいは、シンボル情報のないプロファイルの場合:
その後は、コラプスされたスタックを可視化するために利用できるツールが多数あります。
最も広く使われているのは FlameGraph で、flamegraph.pl というスクリプトが含まれています。
もう 1 つ便利なツールとして speedscope があり、収集したスタックをよりインタラクティブに分析できます。
プロファイラ用の追加オプション
jemalloc にはプロファイラに関連する多くのオプションがあり、MALLOC_CONF 環境変数を変更することで制御できます。
例えば、メモリ割り当てサンプル間の間隔は lg_prof_sample で制御できます。
ヒーププロファイルを N バイトごとにダンプしたい場合は、lg_prof_interval を有効にします。
利用可能なオプションの完全な一覧については、jemalloc の リファレンスページ を参照してください。
その他のリソース
ClickHouse/Keeper は、jemalloc 関連のメトリクスをさまざまな方法で公開します。
これらのメトリクスは相互に同期されておらず、値がずれる可能性があることを認識しておくことが重要です。
システムテーブル asynchronous_metrics
システムテーブル jemalloc_bins
すべてのアリーナから集約された、さまざまなサイズクラス(bin)における jemalloc アロケータによるメモリ割り当てに関する情報を含みます。
Prometheus
asynchronous_metrics に含まれるすべての jemalloc 関連メトリクスは、ClickHouse と Keeper の両方で Prometheus エンドポイントからも公開されます。
Keeper における jmst 4LW コマンド
Keeper は jmst 4LW コマンドをサポートしており、基本的なアロケータ統計情報を返します。