読者です 読者をやめる 読者になる 読者になる

アラタナエンジニアブログ

aratana Engineer's Blog

PHPのextensionを簡単に作れるZephirを使って、EC-CUBEの処理高速化

PHP

はじめまして。アラタナの森藤です。
普段はEC-CUBEベースの自社パッケージ「カゴラボ」の開発マネージャーをしています。

今回はPHPのextensionを簡単に開発出来る新しい言語、「Zephir」を使ってEC-CUBEの中身PHPの関数を置き換えてみたいと思います。
ZephirはPHPの高速フレームワーク「phalcon」の次期バージョン2系で全面採用されています。

・Zephirのインストール(環境:CentOS6.4)

# cd /usr/local/src/
# git clone https://github.com/phalcon/zephir
# cd zephir/
# ./install
./install: line 11: re2c: コマンドが見つかりません
error: re2c is not installed

re2cというパッケージが無い、と怒られましたのでyumでインストールします。

# yum install re2c

インストールが出来たら、Zephirをインストールします。

# ./install-json
# ./install -c

で完了です。

・まずは簡単に変更できそうなEC-CUBEのSC_Utils内の関数を確認
EC-CUBE2.13.2の環境では、データサイズ取得の関数は以下となっています。

data/class/util/SC_Utils.php

public function getUnitDataSize($data)
{
    if ($data < 1000) {
        $return = $data . "KB";
    } elseif ($data < 1000000) {
        $return = $data/1000 . "MB";
    } else {
        $return = $data/1000000 . "GB";
    }

    return $return;
}

データサイズを見て、KB(キロバイト)、MB(メガバイト)、GB(ギガバイト)に分けて文字列を付与して返す関数です。
内容としてシンプルなので、これを置き換えてみたいと思います。

・Zephirのコードを書く

以下手順でZephirの準備をします。
任意のディレクトリに移動後、以下コマンドを実行します。

# zephir init eccfunction

するとeccfunctionディレクトリが生成され、中にディレクトリ/ファイルが生成されます。

-rw-r--r-- 1 root root 1124  1月 20 15:11 2015 config.json
drwxr-xr-x 3 root root 4096  1月 20 15:11 2015 ext
drwxr-xr-x 2 root root 4096  1月 20 15:11 2015 eccfunction

次にeccfunctionディレクトリ以下に移動し、コードを書きます。
ファイル名はEccfunction.zepにします。拡張子は.zepなので注意。

namespace Eccfunction;
class Eccfunction{
    public static function getUnitDataSize(data)
    {
        var return_data = "";
        if (data < 1000) {
            let return_data = strval(data) . "KB";
        } else {
                if (data < 1000000) {
                        let return_data = strval(data/1000) . "MB";
                } else {
                        let return_data = strval(data/1000000) . "GB";
                }
        }
        return return_data;
    }
}

zephirに変更するに当たっての変更点としては

・$は使えないので全て除去
・elseifは使えないのでロジック変更
・今回、数値型と文字列型を結合しているのでエラーとなるため、strvalにて数値型を文字列型に変換後に結合
・変数上書きにはletを指定する必要がある

といった変更点を反映する必要があります。

保存したら、1つ上の階層に移動し、ビルドコマンドを実行します。

$ zephir build
Compiling...
Installing...
Extension installed!
Add extension=eccfunction.so to your php.ini
Don't forget to restart your web server

というような表示が出れば成功です。
php.iniに

extension=eccfunction.so

を追記し、apache等のWebサーバーを再起動して設定を反映してください。
次に、既存関数を置き換えます。
今回はカテゴリCSVアップロード機能で利用されている分を置き換えます。

data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSVCategory.php

118 //$this->max_upload_csv_size = SC_Utils_Ex::getUnitDataSize(CSV_SIZE); //
119 $this->max_upload_csv_size = Eccfunction\Eccfunction::getUnitDataSize(CSV_SIZE); //新しく作成した関数

これで完了です。
アップロードが正常に出来ることを確認してください。

今回の例では画面表示が速くなるような、目に見えてパフォーマンスが大きく改善する程の差はありませんが、
EC-CUBEのutils系のものを順次置き換えていくことで、1処理あたりの速度が数倍に改善されますので、
ちりも積もれば、、的な改善で高速化が見込めます。

まずはutils系の軽い物、次に処理の重い大きな処理を置き換えていくことで、
1リクエストあたりの表示が改善された結果、インフラにかかるコストの削減につながります。

これまでPHPのextensionの作成は敷居が高かった分野ですが、Zephirで簡単に実現が出来るので、是非試してみてください!