【改訂版】FuelPHPのAgentクラスが重い問題と暫定的な対処方法
「FuelPHPのAgentクラスが重い問題と暫定的な対処方法」の改訂版です。
問題の所在
FuelPHP 1.xには、ブラウザ種別、バージョン、プラットフォーム、OSなどを取得するAgentクラスがありますが、その処理が重い、メモリ消費が大きいという問題です。
Agentクラスが使用するブラウザ情報が記録された「browscap.iniファイル」が大きくなったことに比例して、処理が重くなります。
詳細は、FuelPHPのAgentクラスが重い問題と暫定的な対処方法を参照してください。
前回は、browscap/browscap-phpを使う方法を書きましたが、その後も「browscap.iniファイル」が大きくなっており、更新時のメモリ消費が半端なく大きくなってしまっています。
対処方法
今回、新たに別のライブラリを使います。
3. Crossjoin\Browscapを使う
Crossjoin\Browscapは、「browscap.iniファイル」を利用してエージェントの判定をするライブラリです。
高速であり、メモリ消費を抑えた実装になっています。
現状では、Welcomeコントローラのaction_index()メソッドにecho Agent::browser();
を追加すると、browscap-php
では以下のようになりました(Mac OS Xでの結果)。
Page rendered in 0.0709s using 8.934mb of memory.
これが、Crossjoin\Browscap
では、以下のように改善されました。
Page rendered in 0.0656s using 0.59mb of memory
さらに詳細なライブラリのベンチマーク結果は以下を参照してください。
インストール方法
まず、Crossjoin\Browscap
をComposerでインストールしてください。
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,8 @@
"fuel/parser": "dev-1.8/develop",
"fuelphp/upload": "2.0.2",
"monolog/monolog": "1.5.*",
- "michelf/php-markdown": "1.4.0"
+ "michelf/php-markdown": "1.4.0",
+ "crossjoin/browscap": "1.0.*"
},
"require-dev": {
"fuel/docs": "dev-1.8/develop"
Agentクラスへの暫定的な修正パッチは以下になります。
--- a/classes/agent.php
+++ b/classes/agent.php
@@ -195,8 +195,33 @@ class Agent
// try the build in get_browser() method
if (ini_get('browscap') == '' or false === $browser = get_browser(static::$user_agent, true))
{
+ // if it fails, use Crossjoin\Browscap
+ $cacheDir = APPPATH.'cache/fuel/agent';
+ \Crossjoin\Browscap\Cache\File::setCacheDirectory($cacheDir);
+ \Crossjoin\Browscap\Browscap::setDatasetType(\Crossjoin\Browscap\Browscap::DATASET_TYPE_SMALL);
+ $updater = new \Crossjoin\Browscap\Updater\None();
+ \Crossjoin\Browscap\Browscap::setUpdater($updater);
+ $browscap = new \Crossjoin\Browscap\Browscap();
+ $browser = (array) $browscap->getBrowser(static::$user_agent)->getData();
+ // fix any type issues
+ foreach ($browser as $var => $value)
+ {
+ if (is_numeric($value))
+ {
+ $browser[$var] = $value + 0;
+ }
+ elseif ($value == 'true')
+ {
+ $browser[$var] = true;
+ }
+ elseif ($value == 'false')
+ {
+ $browser[$var] = false;
+ }
+ }
+
// if it fails, emulate get_browser()
- $browser = static::get_from_browscap();
+// $browser = static::get_from_browscap();
}
if ($browser)
この場合も、cronなどで以下の処理を実行し、browscap.iniファイルを別途更新する必要があります。
タスクは以下のようになります。
<?php
namespace Fuel\Tasks;
class Agent
{
public static function update()
{
$cacheDir = APPPATH.'cache/fuel/agent';
\Crossjoin\Browscap\Cache\File::setCacheDirectory($cacheDir);
\Crossjoin\Browscap\Browscap::setDatasetType(\Crossjoin\Browscap\Browscap::DATASET_TYPE_SMALL);
$browscap = new \Crossjoin\Browscap\Browscap();
$settings = $browscap->getBrowser()->getData();
}
}
また、Crossjoin\Browscap
は、更新時のメモリ消費も抑えるような実装になっており、
browscap-php
で381,943,808バイト必要だったものが、Crossjoin\Browscap
では62,652,416バイト(約1/6)で済みました(CentOS 6.5 64bitでの結果)。
まとめ
get_browser()関数互換のbrowscap.iniを使ったユーザのブラウザ判定には、Crossjoin\Browscapをお薦めします。
関連
Date: 2015/02/26