phptop_hook.phpでサイトのパフォーマンス測定

PHPのパフォーマンスを計ることができる、phptop_hook.phpを導入してレンタルサーバーのパフォーマンスを測定しました。本稿では解析結果とともに、Excel2010を使ったデータ処理の方法について書きたいと思います。フィルタやピボットテーブルなど、知っていると便利なEcxelの機能を使います。

尚、下記の結果は現在の私の環境(PHP、WordPress、プラグイン及びレンタルプランと割り当てサーバー)での結果です。それぞれのバージョンやプラン、実際にホスティングされたサーバー等で異なると思いますので、参考程度に留めてください。

解析結果

最初に解析結果から書きます。

概要

解析した期間は一週間です。平均値は以下の様になりました。

項目 平均値
時間 0.324 sec
ピーク時のメモリ使用量 15.4 MB
エラーなしアクセス件数 2588
エラー発生アクセス件数 1177
エラー率 31.3%

エラー率30%はつらいですね。(;;

エラー率80%以上(普段において3回はリロードが必要)のURLを見てみると、/wp-admin/network/以下や/wp-admin/post.phpへのクエリでした。

ネットワークの管理や、記事の投稿自体が難しい現状を表しています。(プラグインの検索などは、最早行ってすらいません。^^;)

致命的なのは、サイトのトップページのエラー率が30%だったことです。これはユーザーの離脱につながりますので何とかしないといけません。

メモリ使用量とエラー率の関係

メモリ使用量とエラー率の関係をプロットしてみると上のようになりました。一プロットは、一URL(クエリー含む)に対応します。横軸の単位はMBです。

PHPがどのようにメモリを確保しているか知りませんが、メモリ使用量はおおよそ16MB近辺と22MB近辺に集中しています。そしてその2つのエリアでエラーが発生しています。

メモリを25MB以上使っているにも関わらず、エラーが発生していないURLをみると、wp-admin/options-general.phpとwp-admin/admin-ajax.phpでした。特にadmin-ajax.phpは20回ほど呼び出されています。

確かに16MB近辺より22MB近辺の方がエラー率が高めですが、メモリ使用量と相関があるとは言えません。

(エラー100%のURLについては、phptop_hook.phpがデータを吐き出す機会自体がありません。従ってメモリ使用量が0になって、左上に表示されてしまいます。)

実行時間とエラー率の関係

実行時間(システム時間+ユーザー時間)とエラー率をプロットしてみました。横軸の単位は秒です。CPU占有時間が長いとエラーが起きやすいというわけではありません。

結論は、サーバーが忙しいときはWordPressを使っている限り500エラーが出てしまうのではないでか、ということです。プラグインの見直しを行っても効果なさそうです。(もともとプラグインは最小限にしています。)

その他参考

上がメモリ使用量対実行時間、下がメモリ使用量対総時間(待ち時間も含む)です。サーバーのパフォーマンスや、DBサーバーも含めたシステムのパフォーマンスが比較できそうです。

phptop_hook.php

phptop_hook.phpの導入については、くにくにネットさん「さくらのレンタルサーバーでPHPのメモリ使用量を把握する方法」を参考にさせて頂きました。

その他多くのブロガーさんがphptopを紹介していますので、その導入方法は割愛いたします。

phptop_hook.phpはtime、sys、user、memの4つを出力します。それらの値が何で、単位は何なのか?phptop_hook.phpの中を見ると簡単にわかります。

まずtimeはphpファイルが呼び出されてから、実行し終わるまでの時間を秒で表しています。microtime(TRUE);という関数を使っています。

memは「システムが割り当てた実際のメモリの大きさ(Byte)」で、memory_get_peak_usage(TRUE);にて取得しています。

最後にsysとuserはシステム時間とユーザー時間(秒)で、getrusage();にて取得しています。システムファンクションコールなのでカーネルから取得しているようです。

これらをerror_log関数で、エラーログに出力しています。

私は、解析するに当たって始めてphptop_hook.phpのソースを見たのですが、最初にソースを改造していれば、以降のExcelの操作はもっとシンプルにできましたね。orz

Excelでのエラーログ解析

通常はphptopというperlのツールで集計するようですが、くにくにネットさん曰く「いろいろと面倒だったので使いませんでした。」とのことです。そこでExcel2010を使うことにしました。前述のようなグラフを書くことも目論んでの選択です。

この節ではExcel2010のフィルタ機能やピボットテーブルを使って、エラーログを解析する操作を詳説します。(世の中ビッグデータですが、Excelでもいろいろできます。^^)

Excel上でエラーログを開く

まずExcel上にエラーログを開き、適当な列に分割します。

レンタルサーバーのエラーログは/home/user/log(userは各ユーザー名)にありますので、必要な期間のerror_log_xxxxxxxx.gzをFTPでGETし解凍します。(各位の環境によって、パスやファイル名が異なります。)それらをテキストエディタで開き、Excelのシートににすべてコピペします。

この時点ではすべてA列にデータがありますので、適当な列に分割します。

A列を選択し、データリボンから「区切り位置」をクリックすると、「区切り位置ウィザード」が開きます。

「カンマやタブ…」をチェックして、「次へ」をクリックします。(固定位置でもよさそうですが、clientのIPアドレス以降がガタガタですので。)

区切り文字の「その他」をチェックし、’]’を指定します。そして完了をクリックします。

次にD列を選択し、再び「区切り位置」をクリックします。ウィザードの最初の画面では、先と同様に「カンマやタブ…」をチェックして、「次へ」をクリックします。

今度は区切り文字に「スペース」を選択して「完了」をクリックします。

必要なデータのみのシートの作成

次に、phptopの出力と、500エラーの出力と考えられる「Premature…」のエラーの行だけ、Excelの「フィルタ」機能を使って違うシートにコピーします。(「Premature…」エラーはPHPの実行時エラーでも出力されますので、そのような欠陥は除去されているという前提です。)

1列目に空行を挿入し、データリボンより「フィルタ」をクリックします。すると1行目の各セルに「▼」が表示されますので、E列の「▼」をクリックしてプルダウンを表示します。

「(すべて選択)」のチェックを外した後、「phptop」及び「Premature」をチェックし、「OK」をクリックします。すると「phptop」と「Premature」のレコードのみが表示された状態になります。

Ctrl+Gで「ジャンプ」を開きます。

「セル選択」をクリックします。

「可視セル」を選択し、「OK」をクリックします。すると表示されたセル(つまり「phptop」と「Premature」の行)のみが選択された状態になります。

Ctrl+Cでコピーし、別のシートにCtrl+Vでペーストします。(長時間かかる旨の警告がでたりします。)

このシートの名前を「source」とします。

データの整形

シート「source」を解析しやすいようにもう少し整形します。先ほどと同様に1行目にフィルタを作成します。

まずphptopのF列がURL、G-J列がデータなので、Prematureもそれに合わせたいと思います。

E列の「▼」をクリックしてプルダウンを開き、フィルタを操作してPrematureのみ表示します。

フィルタの直下に表示された行のF列をクリックし、’=’を入力します。その後同行のL列をクリックして、F列にURLが表示されるようにします。

そしてセルの右下をダブルクリックすると、以降の行がすべて同じ式になります。

続いてG-J列を選択しDeleteを押してクリアします。

再びE列のプルダウンから「(すべてを選択)」をチェックして、全ての行を表示させます。

次に、データのG-J列をもう少し分割します。各列の後ろに空列を挿入します。(列を選択後、右クリック>挿入で前に列が挿入されます。)

「mem:」の列の後ろには、もう一列挿入します。(後ろに’,’がついている場合があるので。)

このように、H、J、L、N、O列の空列が挿入されました。

G列を選択し、「データ」リボンの「区切り位置」をクリックし、「カンマやタブ…」をチェックしして次に進みます。

区切り文字に、カンマと、その他に’:’を選択し、「完了」をクリックします。同様にI、K、M列についても区切り位置を指定します。

このようになります。1行目のF、H、J、L、N列に、それぞれ’URL’、’time’、’user’、’sys’、’mem’のようにラベルを書いて、もはや必要のないG、I、K、M、O列は削除します。(列を選択し、右クリック>削除)

Prematureのデータに印があったほうがいいですね。再びE列のフィルタでPrematureだけ表示させます。

そしてフィルタの次に表示されている行のK列に’1’を入力し、右下をダブルクリックします。するとPrematureのK列がすべて’1’になります。

E列のフィルタを「(すべて選択)」に戻し、K1のセルにラベルを書きます。とりあえず「is Premature」としました。

以上で、データの整形は終了です。

ピボットテーブルの作成

次にピボットテーブルを作成して、URLごとに各データの平均を求めます。同時にエラー率のもととなる、成功数とエラー数を集計します。

「挿入」リボンの「ピボットテーブル」をクリックします。

「テーブル/範囲」の右のボタンをクリックします。

F-K列を選択し、ダイアログボックスの右のボタンをクリックします。

「新規ワークシート」を選択し「OK」をクリックします。

新しいシートが作成され、ピボットテーブルを作成する準備ができました。

パネル上部の「URL」を下の「行ラベル」のエリアにドラッグ&ドロップします。

表に行ラベルが追加されます。次に「time」を「Σ値」のエリアにドラッグ&ドロップします。

「データの個数」と表示されますので、クリックしてメニューを開き、「値フィールドの設定」をクリックします。

集計方法を「平均」にして、「OK」をクリックします。同様に、user、sys、memについても、「Σ値」に加えて平均にします。

最後に「is Premature」と、もう一つ「time」を「Σ値」に加えます。これらは「データの個数」のままで構いません。(それぞれ、エラーの発生数と正常終了数になります。)

URLのA列の幅が広すぎるのですが、スクロールさせるとピボットテーブルが完成しています。

例えば「平均/mem」の列のデータを右クリックし、「並べ替え>降順」をクリックすると、メモリ消費の大きい順に行が並び変わります。

以上でピボットテーブルが完成しました。

解析

ピボットテーブルで解析してもいいのですが、癖があるので別のシートに値をコピペして解析用にしたいと思います。

まずピボットテーブルのデータをCtrl+A、Ctrl+Cでコピーします。

そして空のシートを開きます。「ホーム」タブの「貼り付け」の下の▼よりプルダウンを開き、「値の貼り付け」の左のボタンをクリックします。

先頭の空行の削除し、一行目のラベルの整理をしました。そして、H2に「=F2/(F2+G2)」のような式を入力します。(エラー率です。)セルの右下ダブルクリックですべての行に展開します。

ざっとデータを見て、いらない行(URLがない行や、最後の総計の行)を削除します。

後は、time対memの散布図、mem体エラー率の散布図など書けば、解析できそうですね。

先の解析結果では実行時間「=C2+D2」を表示する列と、MB単位のメモリ使用量「=E2/1000000」を表示する列も作成しています。

まとめ

WordPressのサイトにおいて、phptop_hook.phpでパフォーマンスを1週間測定しました。そのエラーログをExcel2010に張り付けて解析しました。

恐らくですが、メモリ使用量を全て15MB以下に抑えることができれば、快適になるかもしれません。しかしWordPressを使っている限り難しそうです。(プラグインも現時点でそれほど使っていません。)

コメントを残す