OpenPNE3.6beta11のORMを変更する実験をしました
11 / 08 火曜日 2011
OpenPNE3にある現状の課題の一つにパフォーマンスの問題があります。OpenPNE3がサーバーに要求するスペックはOpenPNE2よりも高く、OpenPNE3へのアップグレードを敬遠する理由の一つとなっています。そこで、もしOpenPNE3で使用しているDoctrine1を別のORMで置き換えるとどの程度パフォーマンスが改善されるかを実験しました。
環境
- basho1 (芭蕉1 / Webサーバ)
- Intel Core 2 Quad Q8400S 2.66GHz / 4GB Memory
CentOS 5.5
PHP 5.3.3 / APC 3.1.9 / XHProf 0.9.2
Apache 2.2.3
- basho3 (芭蕉3 / DBサーバ)
- Intel Core i5 i5-760 2.80GHz / 8GB Memory
CentOS 5.5
MySQL 5.1.53
詳細は http://d.hatena.ne.jp/openpne/20110823/1314078181 を参照して下さい。
比較したORM
- Doctrine 1.2.4 (OpenPNE3標準)
- Propel 1.6.2
- php-activerecord 1.0
- Doctrine 2.2.0-DEV
DBサーバにメンバーが380,000人登録されている状態で、検索クエリを設定していない状態の「メンバー検索」ページにてXHProfを使用して計測しました。
比較のために使用した修正版OpenPNE3のソースコードは下記URLから入手できます。
- https://github.com/upsilon/OpenPNE3/tree/propel
- https://github.com/upsilon/OpenPNE3/tree/activerecord
- https://github.com/upsilon/OpenPNE3/tree/doctrine2
結果
処理時間
doctrine1 | propel1.6 | php-activerecord | doctrine2 | |
Total Incl. Wall Time (microsec) | 885,274 | 457,233 | 477,260 | 383,231 |
Total Incl. CPU (microsec) | 784,880 | 367,944 | 387,942 | 332,949 |
処理時間では Doctrine1 > php-activerecord > Propel > Doctrine2 の順となりました(短いほど良好)。グラフからも分かるとおりDoctrine1は圧倒的に時間が掛かっています。一方、それ以外のORMではあまり変わらない結果となりました。
メモリ使用量
doctrine1 | propel1.6 | php-activerecord | doctrine2 | |
Total Incl. MemUse (bytes) | 21,630,856 | 20,403,448 | 14,256,808 | 16,358,240 |
Total Incl. PeakMemUse (bytes) | 21,947,888 | 20,609,392 | 14,485,672 | 16,603,624 |
メモリ使用量では Doctrine1 > Propel > Doctrine2 > php-activerecord となりました(少ないほど良好)。PropelがDoctrine1と同じくらいのメモリ使用量になるのは予想外でした。ただ、MemUseとPeakMemUseの差はどのORMでもほとんど変わらないため、メモリ使用量の改善はORM以外の処理でオブジェクトが解放されるように工夫する必要がありそうです。
Function call数
doctrine1 | propel1.6 | php-activerecord | doctrine2 | |
Number of Function Calls | 184,078 | 76,753 | 87,364 | 69,613 |
Function call数についても比較しました。これは Doctrine1 > php-activerecord > Propel > Doctrine2 の順でした(少ないほど良好)。ここでもDoctrine1が特に悪い結果となりました。
変更に要する作業量
OpenPNE3ではプラグインが現在 plugins.openpne.jp に登録されているだけでも80個近く存在し(2011年11月現在)、ORMを変更した場合はこれらの内データベースを使用するほぼ全てのプラグインで修正を行う必要が出てきます。そのため、ORMを変更する場合は単純にパフォーマンスが良いというだけでなくDoctrine1からの移行のし易さも考慮する必要があります。
Propelは、現在Doctrine1で使用しているのビヘイビアやi18nに相当する機能を備えており、sfPropelORMPlugin によってsymfony1.4環境でも問題なく使用することができるため、他のORMと比べると格段に移行し易いです。ただし、それでもschema.ymlの変更やモデルクラスの大幅な修正が必要になるため、移行作業はかなりの時間を要します。参考までに、今回の実験のためにメンバー一覧のページをPropel向けに修正するために15日(通算56時間)ほど掛かりました。
php-activerecordは、現時点でsymfony1.4向けのプラグインが提供されておらず(今回はORMの比較のために作成した sfActiveRecordPlugin を使用しています)、今までのようなsymfonyのタスクによるテーブルの作成やfixtureの挿入は一から実装する必要があります。また、i18nに相当する機能はORM側で用意されておらず、どのように対応するかが課題になります。
Doctrine2は、symfony1.4向けプラグインとして sfDoctrine2Plugin が提供されていますが実質メンテナンスされておらず、最新版のDoctrine2には対応できていません。i18nはORM側の機能としては用意されていませんが、DoctrineExtensions などを利用することでそれに相当する機能を使えるとのことです(ただし今回の検証ではうまく動作しなかったため使用しませんでした)。
このような現状から、単純に移行に掛かる作業量だけを考えた場合はPropelがベターな選択肢となります。
# もちろんORMを変更する必要がなければ作業量はゼロです :)
まとめ
処理時間 | メモリ使用量 | ORM変更の作業量 | |
Propel | ○ | △ | ◎ |
php-activerecord | ○ | ◎ | × |
Doctrine2 | ◎ | ○ | △ |
結果をまとめると上記の表のようになりました。全体的なパフォーマンス面ではDoctrine2、移行のための作業量を考慮するとPropelが良い選択肢となりそうです。いずれにしても処理時間では最大で4〜5割の改善は見込めることが分かりました。
結果データなど
今回の実験で得られたXHProfのデータを下記URLで公開しています。
Doctrine1:
- HTML: https://ty.upsilo.net/openpne-xhprof/?run=doctrine1&source=member_search
- XHProfデータ: https://ty.upsilo.net/openpne-xhprof/raw/doctrine1.member_search.xhprof
Propel:
- HTML: https://ty.upsilo.net/openpne-xhprof/?run=propel&source=member_search
- XHProfデータ: https://ty.upsilo.net/openpne-xhprof/raw/propel.member_search.xhprof
php-activerecord:
- HTML: https://ty.upsilo.net/openpne-xhprof/?run=activerecord&source=member_search
- XHProfデータ: https://ty.upsilo.net/openpne-xhprof/raw/activerecord.member_search.xhprof
Doctrine2:
トラックバック:1
- ピンバック from OpenPNE 3.7 開発仕様について。【beta版】 - besocial.jp 11-11-11 (金) 13:06
-
[…] そして、OpenPNE3では、以前にもopenpne.jpのブログで「OpenPNE3.6beta11のORMを変更する実験をしました」という記事がありましたが、OpenPNE3が抱える問題としてスピード(レスポンス)が遅い […]