PHP・GCの話-7話)GC 関連機能紹介 1 (GC Statistics)



PHP・GCの話-7話)GC 関連機能紹介 1 (GC Statistics)

前書き

  • すべての記事は、自分の勉強目的と主観の整理を含めています。あくまで参考レベルで活用してください。もし誤った情報などがあればご意見をいただけるととっても嬉しいです。
  • 内容では、省略するか曖昧な説明で、わかりづらいところもあると思います。そこは、連絡いただければ補足などを追加するので、ぜひ負担なくご連絡ください。
  • 本文での「GC」は、「Garbage Collection, Garbage Collector」の意味しており、略語として使われています。
  • この記事は、連載を前提に構成されています。

※ 連載目録

※ 連載で使うサンプルコード

Sample Code Link on Github

● ExampleGc.php : 2話から6話までの内容で使うサンプルコードです。
● ExampleWeakReference : 8話のWeakReferenceの内容で使うサンプルコードです。

本連載記事は、基本的にこのサンプルコードをベースに説明をしています。
サンプルコードは、必ず見る必要も実行してみる必要もありません。
各話ごとに、コードを分解して動作原理と結果を解説しますので、基本記事の内容で足りるように心がけます。
あくまで、全体コードをみたい、手元で回してみたい、修正して回してみたいという方向けです。

今回の話

今回は、以下のものを話そうと思うます。

    1. GC Statistics

1. GC Statistics

1) GC Statisticsとは?

https://xdebug.org/docs/garbage_collection

XDEBUG 2.6 から基本提供している GC 分析ツールです。

1話でお話しした内容のように、PHPでは少ないケースだとしても、GCが起きているということ自体が危険信号であり、時々深刻なトラブルになる場合もあります。ですので、どこでGCが起きて、実行されて、どういう影響を与えたのかを分析し理解するのは、メモリとGC関連の問題で必要になってきます。

GC Statisticsは、GCの発動タイミング・実行時間・メモリ確保数値などの情報を分析できるデータを提供します。

PHP の内装エンジンでは GC分析機能を提供していないため、XDEBUGが必須になります。

設定方法としては、「PHP実行オプションでの指定・コード上での呼び出し・xdebug config file でのログ設定」がありますが、今回は「xdebug config file でのログ設定」で、実際に設定と結果分析をしてみます。

2) GC Statistics 設定

‘xdebug.ini’に、以下の設定構文を追加します。
追加すると、指定したディレクトリにログが残るようになります。

1
2
3
xdebug.gc_stats_enable=true
xdebug.gc_stats_output_dir=/var/log/xdebug/
xdebug.gc_stats_output_name=gcstats.%p

3) GC Statistics 結果確認

連載で使っていたサンプルコードを実行した後、GC ログを確認します

1
artisan example:gc
1
2
3
4
5
6
7
8
9
10
11
root@5410ce51b72f:/var/www/html/home_sub/cgi# cat /var/log/xdebug/gcstats.24

Garbage Collection Report
version: 1
creator: xdebug 2.8.1 (PHP 7.4.8)

Collected | Efficiency% | Duration | Memory Before | Memory After | Reduction% | Function
----------+-------------+----------+---------------+--------------+------------+---------
8986 | 89.86 % | 0.00 ms | 82832744 | 37144896 | 55.16 % | App\Console\Commands\ExampleGc::makeGarbageReferenceTo10000CountWhichPHPDefaultRootBufferMax
9948 | 99.48 % | 0.00 ms | 167142328 | 121054232 | 27.57 % | App\Console\Commands\ExampleGc::makeGarbageReferenceTo10000CountWhichPHPDefaultRootBufferMax
1094 | 10.94 % | 0.00 ms | 121502976 | 16173928 | 86.69 % | gc_collect_cycles

各項目に関しての定義は、以下になります。

  • Collected
    • GC により解除されたroot zvalsの数を意味します。解除された root zvals は、root buffer内で、GC による解除対象として監視下にあった、Object、または Array を意味します。
  • Efficiency%
    • root zval 解除効率を表します。計算式はCollected roots count / 10000です。ここで 10000 は、以前紹介したGC_ROOT_BUFFER_MAX_ENTRIESと関係しています。ここの効率が低いということは、GC でも解除できないメモリリック・または欠陥がある可能性が大きいと言えます。
  • Duration
    • GC が実行された時間を意味します。長く実行されているほど、システムの負荷はかかり、処理遅延もまた起きているということになります。
  • Memory Before
    • GC を実行する前のメモリ使用量を意味します。
  • Memory After
    • GC 実行完了後のメモリ使用量を意味します。
  • Reduction%
    • メモリ確保効率を意味します。ここの効率が低いということは、GC によりメモリ確保は期待できないということだと言えます。プログラムのメモリ占有問題を根本的なところからみる必要があると言えます。

ここで大事になるのは、効率と実行時間になると思います。

4) いつ使うべきか?

Java ではよく GC Dump とかをみて、GC Tuning とかをする場合も多いですが、
PHP では GC 分析をどこで使えるかと言われると、実に難しいところですね。

自分が考える使い所としては、DB の大容量処理か、ユーザーサービスにおいて、イメージや動画の大容量データを一括変換するような、実行時間が長く、大容量データを扱うサービスでは、メモリや処理に遅延が起きる場合は、調査方法の一つとして考えられるとは思います。

しかし、この内容を言っておく真の意味は、PHP のメモリ管理メカニズムを理解することにあると思うので、どっちかというと、「メモリ管理を意識した設計・実装」において、この知識自体が活用できるんじゃないかなと思います。

後書き

実は、今回を最終話にして、GC Statisticsと、Weak Reference内容を一緒に紹介した上で完結しようと思いましたが、Weak Referenceの分量がやはり多くなって、分けて投稿するようにしました。

実は話したいことが多くなってしまったせいもありますが、Weak Referenceは面白く、これからはPHPでも関心が高くなると思うので、有意義な話になればと思っています。