perf-tools を使ってPHPソースレベルの Flamegraph を作る

2021-05-17
PHP
perf-tools

array_uniquearray_flip x 2回 の速度比較をしていたのですが、マイクロベンチの類なので、普通にプロファイラーで解析してもボトルネックの比較が難しい。というわけで、FlameGraph を出してみた。結果としては、めちゃくちゃ簡単です。

※Linux使っていることが前提です。

事前準備

下記のコマンドで perf-tools をインストールしておく。kernel のバージョンに依存するので、対応するものを都度インストールしておくのが大切。

1
sudo apt install linux-tools-$(uname -r) linux-tools-generic

perf の出力から、FlameGraph を作成するツールを clone しておく。リポジトリは下記。

https://github.com/brendangregg/FlameGraph

解析対象のPHPスクリプト

FlameGraph を出力したい PHP のスクリプトを書く。ご覧の通りの無限Loopです。きれいな FlameGraph を出すために、とにかくたくさん実行します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

// 適当に重複がある配列を作る
$dup = [];
for ($i = 0; $i < 80000; $i++) {
if($i < 30000){
$dup[] = $i;
}
$dup[] = $i;
}


//テスト対象のメソッドでユニークする
while(true){
array_unique($dup, SORT_STRING);
}

FlameGraph を生成するスクリプト

基本的には、 FlameGraph のウェブサイトのトップページに書かれている使い方に即しています。めんどうなのでシェルスクリプトにしただけです。

PHPスクリプトをバックグラウンド実行して PID を取得して、そのPIDに対して perf-tools でサンプリングして、FlameGraph ツールで svg を出力します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

PHP='/usr/local/bin/php'
SCRIPT='/tmp/foo.php'
CMD=$PHP' '$SCRIPT
FLAME_DIR='/FlameGraph'
OUTFILE=`date +"%Y-%m-%d-%H%k%S"`_kernel.svg

$CMD &

pid=$!

perf record -F 99 -p $pid -g -- sleep 30
kill $pid

perf script > out.perf
$FLAME_DIR/stackcollapse-perf.pl out.perf > out.folded
$FLAME_DIR/flamegraph.pl out.folded > $OUTFILE

出力例

ペア [もっと大きく見たい場合はこちら](/images/flame/flame_array_unique_string.svg)