軽量なPHP FrameworkのFuelPHP1.5.3を利用することになったのでお勉強開始。itemsテーブルをTASKのfromdbでscaffold。

php oil refine fromdb:scaffold --force items

ここで生成されたスケルトンをカスタムして、一般的なDBデータを一覧表示を実装するテストを実施してみたが、1ページあたりの表示可能件数を指定できるようになったところで100,300,500件の表示をすると結構応答が遅いことに気がついた。
サーバースペックはCPU AtomD525・Memory 4GB・SSDなので、さほど速いPCでもないが、このくらいで遅くなるのもちょっと変だなと調べてみた。

FuelPHP Profilerの結果

FuelPHPに付属のProfilerをONにしてみて300件のリストを表示してみると、時間がかかっているところがあるようだ。
しかし、Profilerが優れているなぁ。
・fuel/app/config/config.php

'profiling'  => true,

FuelPHP profiler

XHProfによるプロファイル

次にもっと詳細にプロファイリングするためにXHProfを仕込んで実行してみたところ、2箇所が怪しい。
1つ目は Fuel\Core\Html::anchor 。
できたてのViewはリストの1つ1つの項目でHtml::anchorをCallして、view,edit,deleteのanchor要素をつくるので、Html::anchorは行数×3回呼ばれる。そりゃ遅いしHTMLのデータ量も多くなる。これは全部リンクを作る必要は無いので外す。
すると若干軽くなった。
もう1つはoutput_filterに指定されている、Security::htmlentities。
どうもViewに送られるデータを全部自動的にSecurity::htmlentitiesでフィルターかけるようだ。
これは何となく重そうなので、Security::htmlentitiesを外す方法を調べてみた。

Security::htmlentities を外してみる実験

Security::htmlentitiesを外してテストしてみる。
※実運用ではありません!実運用では何らかの方法で出力を無害化必要!
まずは、configなどはそのままの状態で、Security::htmlentitiesが有効な場合。
fuelphp_many_list_security

500件表示で、7.12秒かかる。
次に、 fuel/app/config/config.php で Security::htmlentitiesが全くかからないようにしてみる。

/**
 * Whether to automatically filter view data
 */
'auto_filter_output'  => false,

fuelphp_many_list_auto_filter_output_false

500件表示で、1.52秒!改善している。
同じようなものだが、'Security::htmlentities'をフィルタから外した。

/**
 * This output filter can be any normal PHP function as well as 'xss_clean'
 *
 * WARNING: Using xss_clean will cause a performance hit.
 * How much is dependant on how much input data there is.
 */
//'output_filter'  => array('Security::htmlentities'),
'output_filter'  => array(),

fuelphp_many_list_output_filter_none

500件表示で、1.53秒! まぁ、そうでしょう。
今度は、output_filterはONだが、コントローラーでViewにデータを渡すときにフィルタされないようにset_safeで渡してみた。

$items = Model_Item::find()
            ->rows_offset($offset)
            ->rows_limit($pagination->per_page)
            ->get();

//$data['items'] = $items;

$this->template->content = View::forge('items/index', $data);
$this->template->content->set_safe('items', $items);"

fuelphp_many_list_setfalse

500件表示で、1.54秒!
あと、config の whitelisted_classes を使う方法もあるかもしれない(未調査)。
FuelPHPで、データが多くパフォーマンスが悪い場合は、Security::htmlentities以外の方法で出力をエスケープするのも1つの方法のようだ。