負荷測定

CakePHPベースの自作アプリケーションのα版を公開環境においてみて一番問題だったのは、負荷でした・・・ アクセス〜表示に数秒かかるとは。


アプリ内部の追加や修正が一通り見込みついたところで、負荷対策開始。


手始めとして、実際に負荷を測定して「見える」状態にするために、Benchmarkコンポーネントを入れました。
ApachBenchは、おそらく要ログイン画面の測定ができないので・・・


参考サイト
pblo | ぴーぶろ : webデベロッパーの勉強メモとか



Benchmarkコンポーネントは、以下のものを使用*1
http://blog.aidream.jp/cakephp/cakephp-benchmark-component-1366.html


init.php(bootstrap.phpから読み込んでいるconfig)にベンチマーク実行定数を設定。

app_controller.phpにて、beforeFilter, beforeRender, afterFilterのタイミングで出力するよう設定しました。


任意のアクション表示で、以下のように出力されます。

[cake@cake chara-shee]$ cat app/tmp/logs/debug.log
2010-07-07 12:57:45 Debug: [4ec45881] 0.00001 : <==construct :
2010-07-07 12:57:45 Debug: [4ec45881] 0.15727 : characters/view: beforeFilterStart :
2010-07-07 12:57:45 Debug: [4ec45881] 0.41819 : characters/view: beforeRenderStart :
2010-07-07 12:57:46 Debug: [4ec45881] 0.99297 : characters/view: afterFilterStart :
2010-07-07 12:57:46 Debug: [4ec45881] 1.01849 : <==destruct :

charactersコントローラのviewアクション表示に、約1秒かかっている、という結果がでました。


ちなみに、Apache Benchで同じページの測定結果。

[cake@cake chara-shee]$ ab -n 10 -c 10 http://hogehoge/characters/view/1

(中略)
Requests per second: 1.27 [#/sec] (mean)

大体あってます。


Benchmarkコンポーネント導入差分
--- a/app/config/init.php
+++ b/app/config/init.php
@@ -39,13 +39,17 @@ Configure::write('Qdmailer', array(
        'errorlogFilename' => 'qdmailer_error.log',
 ));
+
+/* Benchmarkコンポーネント使用 */
+define('BENCHMARK_MODE', true);

--- a/app/controllers/app_controller.php
+++ b/app/controllers/app_controller.php
@@ -30,10 +30,11 @@ class AppController extends Controller
        var $components = array(
                'AuthPlus',
                'Acl',
                'Cakeplus.HtmlEscape',
                'Token',
                'Crypt',
                'DebugKit.Toolbar',
+               'Benchmark'
        );
@@ -100,6 +101,8 @@ class AppController extends Controller

        function beforeFilter()
        {
+               $this->Benchmark->report($this->params['controller']. '/'. $this->action . ':' .' b
+
                parent::beforeFilter();
(以下略)

+++ b/app/controllers/components/benchmark.php
@@ -0,0 +1,54 @@
+<?php
+/*
+ * ベンチマークコンポーネント
+ * Reffer: http://blog.aidream.jp/cakephp/cakephp-benchmark-component-1366.html
+ */
+
+class BenchmarkComponent extends Object {
+       var $id = null;
+       var $start_time = 0;
+
+       //---------------------------------------------------------------------------
+       // コンストラクタ
+       //---------------------------------------------------------------------------
+       function __construct() {
+               $this->id = substr( md5(uniqid(rand(),true)) , 0, 8);
+               $this->report('<==construct', true);
+       }
+
+       //---------------------------------------------------------------------------
+       // デストラクタ
+       //---------------------------------------------------------------------------
+       function __destruct() {
+               $this->report('<==destruct');
+       }
+
+       //---------------------------------------------------------------------------
+       // 計測してログファイルに出力
+       //---------------------------------------------------------------------------
+       function report($message = null, $reset = false) {
+               if (defined('BENCHMARK_MODE') === false || BENCHMARK_MODE === false) {
+                       return;
+               }
+               if ($reset === true) {
+                       $this->start_time = $this->_getMicroTime();
+               }
+
+               $now = $this->_getMicroTime() - $this->start_time;
+
+               $str = sprintf("[%s] %01.5f : %s :", $this->id, $now, $message);
+               $this->log($str, LOG_DEBUG);
+       }
+
+       //---------------------------------------------------------------------------
+       // マイクロタイムを取得
+       //---------------------------------------------------------------------------
+       function _getMicrotime() {
+               if (phpversion() < 5) {
+                       list($usec, $sec) = explode(" ", microtime());
+                       return ((float)$usec + (float)$sec);
+               } else {
+                       return microtime(true);
+               }
+       }
+}

*1:但し、元ソース31行目の変数名と、44行目セミコロンヌケを修正。