はじめに
Magento2(その他PHPのフレームワーク)でエクステンション等の開発をしていると、「なんだか動きが遅いな」と感じることがあると思います。
遅いけどどこで遅くなってしまっているのかわからない。
そんな時に、一連の処理を視覚化し分析することができる「XdebugのProfiler」という機能があります。
今回は試しにDen+Magento2の環境でXdebugのProfilerを使用し、分析を行ってみました。
- PHPStormで分析する手法
- jokkedk/webgrindというツールを用いて分析する手法
上記の2通りで試しました。
補足として、Magentoのコア機能として存在するProfiler機能も紹介します。
環境
Den : 1.0.0-beta.14
Magento2 : 2.4.6-p1
Xdebug : 3.2.1
PHPStorm : 2023.1.3
jokkedk/webgrind : 1.9.2
前提
Den+Magento2のインストールが完了していることとします。(Den+Magento2の環境構築方法はこちらで紹介してます。)
下準備
Xdebugの設定
まず、Xdebugの設定を変更します。
※Cliだけで使いたい場合は、
php -d xdebug.mode=profile bin/magento
と、php cliのdオプションでiniファイルの設定を上書きできるので、以下の設定はスキップできます。
Denの場合、Xdebugが入っているphpコンテナは別に用意されている(php-debug)ため、こちらで作業します。
まず、Denの環境を立ち上げたディレクトリ下に.wardenディレクトリを作成しておきます。
元となるXdebugの設定ファイルをphp-debugコンテナから.wardenディレクトリ下にコピーします。
den env cp php-debug:/usr/local/etc/php/conf.d/15-xdebug.ini ./warden
コピーしてきた15-xdebug.iniに以下のように設定します。
# xdebug.mode = debug; //元の設定
xdebug.mode = profile;
warden-env.ymlを作成します。
services:
php-debug:
volumes:
- ./.warden/15-xdebug.ini:/usr/local/etc/php/conf.d/15-xdebug.ini
Cliコマンドの作成
CliコマンドでProfilerの分析(PHPStorm)
試しに下記のようなCliコマンドを作成し、分析に充ててみます。(思い切って8GBの文字列を生成してみます。)
MagentoにおけるCliコマンドの作成方法はAdobeの公式ドキュメントに載っています。
<?php
namespace Nao\Xdebug\Console\Command;
use Magento\Framework\Console\Cli;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class TestProfiler
*/
class TestProfiler extends Command
{
/**
* @inheritDoc
*/
protected function configure(): void
{
$this->setName('nao:xdebug:test-profiler');
$this->setDescription('Test the Xdebug profiler.');
parent::configure();
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$memoryToUseInMB = 8192;
$largeData = $this->generateLargeDataArray($memoryToUseInMB);
return Cli::RETURN_SUCCESS;
}
/**
* @param $sizeInMB
* @return string
*/
private function generateLargeDataArray($sizeInMB): string
{
$sizeInBytes = $sizeInMB * 1024 * 1024;
return str_repeat('A', $sizeInBytes);
}
}
Cliコマンド実行・出力ファイルの処理
den debugでphp-debugコンテナの中に入り、Cliコマンドをたたきます。(上記のコードの場合はbin/magento nao:xdebug:test-profiler
)
xdebug.output_dir
に設定された保存ディレクトリに、xdebug.trace_output_name
で指定したフォーマットでファイルが出力されます。
出力先のディレクトリは、dockerのvolumeを設定するなり、docker cpするなりしてホスト側にコピーしておきます。
Profilerの分析
準備が整ったので、さっそく分析を行っていきます。
PHPStormによる分析
まず、PHPStormで分析してみましょう。
トップナビのTools > Analyze Xdebug Profiler Snapshot...
から、先ほどホスト側にコピーした出力ファイルを選択します。
しばらく読み込まれるのを待つと、下図のようなタブが開きます。
赤枠の部分を見てみると、Nao\Xdebug\Console\Command\TestProfiler::execute
でMemoryが約8GB使用されていることが分かります。
また、str_repeart
関数の実行に約3秒かかっていることが分かります。
また、下にあるCallersタブで、対象の関数が呼び出される際のコールツリーを見ることができます。
str_repeart
関数が、Nao\Xdebug\Console\Command\TestProfiler::execute
内のNao\Xdebug\Console\Command\TestProfiler::generateLargeDataArray
で呼び出されていることが分かります。
jokkedk/webgrindを用いた分析
ここまでで十分な分析結果を得ることができましたが、もう一つ便利なツールがあります。
それがjokkedk/webgrindです。
docker imageがありますので、それを使用します。
docker run --rm -v ./xdebug:/tmp -p 83:80 jokkedk/webgrind:latest
-v ./xdebug:/tmp
: ./xdebugの部分は、XdebugのProfilerで出力されたファイル(ホスト側にコピーしたもの)が格納されているディレクトリを指定します。
-p 83:80
: 83の部分は、ご自身の環境で使われていないポート番号を指定します。
http://127.0.0.1:83にアクセスし、右上のドロップダウンメニューからファイルを選び、「update」ボタンをクリックします。
Total Self Costとは、対象の関数の、全体に対する処理時間の割合です。str_repeat
の処理時間が全体の80.75%占めているということになります。
また、関数名をクリックすると呼び出し元の表示もできます。
右上のShow Call Graph
をクリックすると、処理の流れを視覚化したグラフを見ることができます。
全体の80.75%を占めるstr_repeat
が呼び出されるまでの処理の一連の流れを見ることができました。
補足
実はMagentoのコア機能としてもProfiler機能が存在します。
下記のコマンドでProfiler機能を有効化できます。
bin/magento dev:profiler:enable [type]
[type]の部分にはhtml
とcsvfile
が指定できますが、特にhtml
を指定するとページにアクセスした際にページの最下部に分析結果がレンダリングされるため、かなり使いやすいオプションです。
詳しくは公式ドキュメントを参照してください。
おわりに
今回は検証のために8GBの文字列を作成するというかなり大げさなことをしたため、とてもあからさまな分析結果となりました笑
しかし、パフォーマンスチューニングをする際にはかなり便利な機能ですので、是非使いこなしていきたいですね!