「カーネル謎機能を活用したパフォーマンスとの戦い」と題してPepabo Tech Fridayで発表していた。ペパボテックフライデーとは下記です。
しかし、割と生々しい社内のプロジェクトの計測値を出しているので、資料は公開しません...(入社したらあるいは... ;) ) が、一般的な内容にしてどこかで話そうという気持ちはある(言ってしまった...)。
続きを読むこのブログは、昨日の分です。だめですかね...
カーネルトレーシングシリーズです。今日は、Nginxを、追ってみます。
大抵の場合、パッケージのnginxバイナリはシンボルがstripされていて、uprobeが見えない。 nginx-build などで自分でビルドする。
トレーシングの都合上、 --with-debug
でビルドするといいらしい( ngx_request_t *
などがトレーサから見えるようになる)。
$ nginx-build -d src/nginx-build -v 1.15.12 \ --with-debug
uprobeは以下の通り確認できる。
$ sudo bpftrace -l 'uprobe:/usr/local/nginx/sbin/nginx' | head uprobe:/usr/local/nginx/sbin/nginx:deregister_tm_clones uprobe:/usr/local/nginx/sbin/nginx:register_tm_clones uprobe:/usr/local/nginx/sbin/nginx:__do_global_dtors_aux uprobe:/usr/local/nginx/sbin/nginx:frame_dummy uprobe:/usr/local/nginx/sbin/nginx:ngx_load_module uprobe:/usr/local/nginx/sbin/nginx:ngx_unload_module uprobe:/usr/local/nginx/sbin/nginx:ngx_set_env uprobe:/usr/local/nginx/sbin/nginx:ngx_set_cpu_affinity uprobe:/usr/local/nginx/sbin/nginx:ngx_set_priority uprobe:/usr/local/nginx/sbin/nginx:ngx_set_worker_processes
まだまだ消費増税に対抗するため、無理やりネタを紡ぎ出す。
named pipe、「名前付きパイプ」の簡単な使い方を残しておく。
プロセスの間でなにかしらのデータのやり取りをすることをプロセス間通信(Inter Process Communication)と呼ぶ。たとえばLinuxでは以下のような方法がある。
この分類は「Linuxプログラミングインターフェース」を参考にした。
IPCで最も手軽なのはパイプの作成で、fork元でpipe()などを用いて読み出し専用/書き込み専用の1組のパイプを作り、fork先でもそのfile descriptorを継承して使う。お互いにread/writeという基本的なシステムコールのみでデータをやり取りできるメリットがある。
mruby(CRubyも同様)の例を昔書いた。
一方でパイプは、fdを共有できるような、例えば親子関係があるプロセス同士でないと利用できない。そこでファイルシステム上に作成できる名前付きパイプを使う。
昨日は普通にブログを忘れていた...。増税に負けてしまった...。
気を取り直して今日。
hacoboot_sampler
というツールをリポジトリに同梱した(名前は...)。
# 第一引数は、コンテナの init のコマンドを推奨 $ sudo bpftrace misc/hacoboot_sampler.bt /u/app/helloworld/bin/rails
こう起動して、別窓でコンテナをあげたり降ろしたりしていると、
のそれぞれの時間を計測し、平均、最大、最小をナノ秒単位で出してくれる。
Attaching 5 probes... ^C @execve__count: 3 @execve_avg: 70950886 @execve_max: 78633157 @execve_min: 59346736 @listen__count: 3 @listen_avg: 2240287035 @listen_max: 2359375184 @listen_min: 2100345924
このコンテナは execveまで平均 78ms、その後リスンしてアクセスできるようになるまで 2240ms かかっているとわかる。コンテナプロセスの起動自体の必要時間が 2100ms 程度ということですね。
スクリプトを参考に、ヒストグラムを出したり他の集計も試せるし、各値をTSVに吐き出してmatplotlibに食わせたり、など、夢が広がる。
今の制限として、initプロセス(スレッド)がそのままlisten(2)を発行するパターンでないとlistenの検知ができない。こういうときに cgroup
が取れるとコンテナ内でのシステムコール呼び出しが紐づくんだけど、今回実際にやりたい環境は諸事情によりUbuntu 16.04なのでカーネルが新しくても4.15で、 BPF_FUNC_get_current_cgroup_id
がないので使えないみたい。
みんな、カーネルどんどん上げていきましょう。Bionicで5.0が使えるんですよ、やばくないですか。
続きを読む