Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP のプロファイルを Grafana Pyroscope で見たくてライブラリを自作した

Chiba Tairi
March 22, 2025
400

PHP のプロファイルを Grafana Pyroscope で見たくてライブラリを自作した

https://fortee.jp/phperkaigi-2025/proposal/d7ad369b-b60b-4502-a958-f475e7ac876c

# 文中の参考文献
Observer API (関数フック方式)
https://www.datadoghq.com/blog/engineering/php-8-observability-baked-right-in/
Pyroscope の SDK で ptrace システムコールを使わない話
https://github.com/grafana/pyroscope/issues/216
pprof 形式について
https://github.com/DataDog/go-profiler-notes/blob/main/pprof.md
Flame Graph を使った性能改善
Beginners Guide - All About Flame Graphs Visualization | Grafanahttps://www.youtube.com/watch?v=VEvK0JkPlOY

Chiba Tairi

March 22, 2025
Tweet

Transcript

  1. 言語を問わないツール • New Relic • Datadog • Pyroscope PHP専用のツール •

    Tideways • blackfire 継続的プロファイリングを提供するツール 4 イントロダクション
  2. 4種のOSSのプロファイラを比較 • longxinH/xhprof • オリジナル xhprof の PHP8 対応版 •

    adsr/phpspy • reliforp/reli-prof • phpspyと似ているが、PHP 製なのでプラグインとしても利用可能 • nikic/sample_prof • コールスタックを一部しか取得しないため fork が前提 比較するプロファイラ 11 PHP プロファイラの選定
  3. プロファイラの分類(再掲) 12 PHP プロファイラの選定 PHPのプロセス タイマー 外部プロセス 関数呼び出しフック xhprof sample-prof

    phpspy reli-prof タイマー方式は オーバーヘッドが小さい PHPプロセスで実行すると 利用する権限が少ない 外部プロセスは オーバーヘッドが小さい フック方式は 実装がシンプル
  4. 測定対象 検証の再現性を確保するために private-isu を利用 • stefafafan/private-isu-php(高パフォーマンスなPHP実装) • catatsuy/private-isu (環境設定・ベンチマーカー) 測定方法

    プロファイル測定時のベンチマーク結果を比較(5回の平均) サンプリング頻度は 100Hz (10 ms) ベンチマーク 16 PHP プロファイラの選定
  5. 240000 250000 260000 270000 280000 290000 300000 310000 320000 プロファイラなし

    phpspy sample_prof reli-prof xhprof 各プロファイラを有効にした際の private-isu のスコア ベンチマーク結果 17 PHP プロファイラの選定
  6. 240000 250000 260000 270000 280000 290000 300000 310000 320000 プロファイラなし

    phpspy sample_prof reli-prof xhprof 各プロファイラを有効にした際の private-isu のスコア さらに低下 (-40000点程度) ベンチマーク結果 17 PHP プロファイラの選定 変化なし すこし低下 (-10000点程度)
  7. pprof 形式 Go などで利用されている pprof 形式で受信 Pyroscope SDK で利用されている、メタデータを付与しやすい テキスト形式

    単純なテキストで受信 仕様が単純すぎて、利用できる機能が限られる Pyroscope のプロファイル受信方法 20 Pyroscope との連携
  8. pprof とは Google 製のプロファイル取得ツール。Go 言語製。 pprof 形式とは pprof が出力する protobuf

    形式のバイナリ pprof 以外にも幅広くプロファイルの転送に利用される pprof とは? pprof 形式とは? 21 Pyroscope との連携
  9. Pyroscope の SDK は pprof 形式で通信している つまり、pprof 形式で通信すれば他言語と同じ機能が使えるはず pprof 形式は

    gzip 圧縮された protobuf らしいので、 他言語の Pyroscope SDK からデータを横取りして見てみる pprof 形式の出力を見てみよう 22 Pyroscope との連携
  10. pprof 形式は単なる protobuf だと最初は思っていたが、 protobuf をデコードすると謎の数値が出現した ただの protobuf じゃないぞ!? 23

    Pyroscope との連携 sample { location_id: 1 location_id: 2 location_id: 3 location_id: 4 location_id: 5 location_id: 5 location_id: 6 location_id: 7 location_id: 5 location_id: 8 location_id: 9 location_id: 10 value: 10000000 label { key: 14 str: 15 } } location { id: 1 line { function_id: 1 } } function { id: 8 name: 7 filename: 12 start_line: 207 } スタックトレースはどこに!?
  11. 非常に複雑な pprof 形式 24 Pyroscope との連携 https://github.com/DataDog/go-profiler-notes/blob/main/pprof.md より 謎の数値はポインタ 例:location_id:

    1 → location の id=1 を参照 プロファイルを小さくするため 複数回出現するデータを全て id で持つ
  12. pprof の出力を読むために pprof デコーダを実装 26 Pyroscope との連携 { "location": [

    { "mapping": null, "address": 0, "line": [ { "function": { "name": "execute", "system_name": "", "filename": "", "start_line": 0 }, "line": 0 } ], "is_folded": false }, ..., ], "value": [ 10000000 ], "label": [ { "key": "xhprof_info", "str": "SELECT `id`, `user_id`, `body`, `mime`, `created_at`...", "num": 0, "num_unit": "" } ] } sample { location_id: 1 location_id: 2 location_id: 3 location_id: 4 location_id: 5 location_id: 5 location_id: 6 location_id: 7 location_id: 5 location_id: 8 location_id: 9 location_id: 10 value: 10000000 label { key: 14 str: 15 } }
  13. Pyroscope との連携の全体図 27 Pyroscope との連携 nginx Pyroscope ユーザー /index.php index.php

    pprof.php /debug/pprof xhprof プロファイル取得 保存 プロファイル データ 読み取り・変換 ユーザーからの アクセス Pyroscope への プロファイル送信
  14. Ruby や Python は作るのに PHP は作らない事情は色々ありそう • Rust 製の rbspy

    や pyspy と違って phpspy は C言語製 • PHP は CGI モデルなので他言語とライフサイクルが違う コミュニティ実装がいくつか現れて、戦国時代に突入 • zoonru/pyrospy • everythings-gonna-be-alright/phpScope Grafana が全然作ってくれないんだけど!? 32 今後の展望
  15. pakutoma/phreakscope Pyroscope 非公式 PHP 向け言語 SDK • 名前の由来:phreak(電話網のhacking)から • Pyroscope

    に「ただ乗り」するので 特徴 • プラグインとして動作するため、コンテナで動かしやすい 戦国時代に名乗りを上げたい 33 今後の展望
  16. • Pyroscope の新機能に追従 • Trace to Profiles • Grafana Alloy

    の Push API • パフォーマンスの向上 • nikic/sample-prof を試す • ドキュメントを充実させる 今後の実装予定 34 今後の展望 https://grafana.com/docs/grafana-cloud/whats- new/2024-01-03-trace-to-profiles/ より
  17. • Grafana Pyroscope で継続的プロファイリングがしたい • でも Pyroscope は PHP に対応していません

    • なので、phreakscope というライブラリを作りました • ただいま絶賛開発中です ありがとうございました! 全体のまとめ 35 まとめ
  18. Observer API (関数フック方式) https://www.datadoghq.com/blog/engineering/php-8-observability-baked-right-in/ Pyroscope の SDK で ptrace システムコールを使わない話

    https://github.com/grafana/pyroscope/issues/216 pprof 形式について https://github.com/DataDog/go-profiler-notes/blob/main/pprof.md Flame Graph を使った性能改善 Beginners Guide - All About Flame Graphs Visualization | Grafana https://www.youtube.com/watch?v=VEvK0JkPlOY さらに詳しく知りたい時の資料 36 おまけ