こんにちは、リモートワーク生活で筋肉が落ちて危機感を感じはじめているサーバエンジニアの山脇です。
今回はタイトルの通りパフォーマンスについてのお話です。
パフォーマンスの話についてはワンダープラネットに入社してから色々やらかして先輩からたくさん注意をもらいました。
注意されたなかでもfor文の中でMySQLサーバからデータを取得するような以下のコードは今見るとひどいなと感じます。
foreach ($element as $elements) {
$rows = $db->getById($element->getId());
...
}
さて、ゲーム以外でもよく使われるAPIサーバですが運営をしていくと、新機能を追加したり、リソースが増えたりといった要因でパフォーマンスの劣化が起こってきます。
また、「この機能は計算量が大きくなるだろうな」と予想される機能や関数については事前にtime関数などを使ってコンソールやログファイルに時間を流して問題ないか確認することもあると思います。
しかし、 API全体でみたい時にいちいち怪しいところにtime関数入れるのは手間になり、かつ間違えてコミットしてしまう恐れもあります。
そんな時に便利なパフォーマンス確認ツールがBlackfireです。
Blackfireとは
PHPのプロファイリングサービス(Beta版としてGoやPythonもサポートをはじめている)
ソースコードを変更する必要がなく、必要なパッケージのインストールだけで使用可能
できること
- 関数が何回呼ばれたか
- 処理にかかった時間
- 処理にかかったメモリ使用量
インストール & 実行
インストール
インストールは 公式ドキュメント がとてもわかりやすくまとまってます。
インストールするマシン、OS、言語などを選ぶと必要なコマンドを出してくれるので迷いにくかったです。
自分たちが使っている環境はcentosでphpを使っていたので以下のコマンドでインストールしました。
# wget -O - "http://packages.blackfire.io/fedora/blackfire.repo" | tee /etc/yum.repos.d/blackfire.repo
# yum -y install blackfire-agent blackfire-php
# blackfire-agent --register --server-id=${BLACKFIRE_SERVER_ID} --server-token=${BLACKFIRE_SERVER_TOKEN}
# /etc/init.d/blackfire-agent restart
# blackfire config --client-id=${BLACKFIRE_CLIENT_ID} --client-token=${BLACKFIRE_CLIENT_TOKEN}
実行
15日の無料トライアル期間を利用したのでAPIサーバ内部からAPIを実行しています。
(APIのbody部を作るのってどのパラメータがいるとか考えるの大変ですよね...)
curlコマンドの頭に blackfire
をつけるだけでプロファイリング結果をBalckfireのウェブページで確認できます。
curl以降は普段使うものとオプションが変わらないのでわかりやすくて良かったです!
# blackfire curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/octet-stream' -d '{}' 'http://127.0.0.1/version'
Unsafe HTTP POST method detected, disabling aggregation.
Blackfire cURL completed
Graph URL https://blackfire.io/profiles/60c327bb-xxxx-yyyy-zzzz-245b83b1a94d/graph
No tests! Create some now https://blackfire.io/docs/cookbooks/tests
No recommendations
↑が実行結果の参考になります。
Graph URL
のURLにアクセスするとグラフィカルに処理内容を確認することができます。
改善ポイントの探し方
Blackfireの実行した内容は以下のようにグラフィカル表示されます。
表示されている内容は
- ヘッダー部
- 実行時間
- 使用メモリ量
- 左ペイン
- 関数名
- かかった時間の割合(赤いバーの部分)
- 処理回数
- 詳細では実際にかかった時間
- 右ペイン
- 各関数の相関図
- かかった時間の割合
- 処理回数
- 割合が高い箇所は太枠になったり、背景色が変わる
(今回は呼び出されている回数が多いのでそこが問題になっているのではないかと推測できます)
あたりの付け方
- 相関図の赤く強調されているところを確認する
- 前後の呼び出し回数を確認
- 呼び出し回数が多い場合はループが妥当か調べる
- 事前にフィルターなどで回数を減らるか
- 余分なデータを取得していないか
- etc...
- 呼び出し回数が多くない場合は内部ロジックを調べる
- SQLサーバからの応答が遅い
- プログラムがO(n)やO(n^2)になっている
- etc..
まとめ
- インストール~実行までがすごく簡単
- 既存のソースコードを変更しなくても良い
- 結果がグラフィカルでわかりやすい
- 呼ばれている回数もわかるので問題の把握がしやすい
最後に
はじめて、自分がパフォーマンス改善について調べた時も問題の箇所の特定からアプローチの手順を間違えて時間がかかりました。
パフォーマンス改善は色々と試行錯誤が必要な場合もあるので、現状の測定、大まかな問題箇所の特定は時間をかけずにサクッと終わらせてより良いパフォーマンスを出していきましょう!