[CodeIgniter] CodeIgniter + SQLite3の処理速度をベンチマーク
CodeIgniter+軽量なデータベースSQLiteの組み合わせで、どれくらいのパフォーマンスが出るのかを調べるために、ベンチマークをとってみました。
更新日: 2018.7.17公開日: 2017.10.11
テスト環境
レコード: 1500レコード * 7カラム
サーバー:MacBook 12インチ Core m7
OS:Ubuntu Server 16.04 on Vagrant (1CPU 2GBメモリ)
PHP:PHP7 on Docker
処理能力はそこそこなサーバー(VPS 1GBプランくらい?)を想定して、仮想マシン上の設定は1CPU * 100%で設定しました。
MacBook 12インチの1CPU * 100%だと、CPU面ではさくらやConoHaなどのVPSの1コアプランよりも処理速度は劣っています(VPSは共有だとしてもXeonですので)。
逆に、Google Compute Engineのf1-microやラズパイクラスのサーバーでは、こんなに速度は出ないと思います。GCPのf1-microはUnixBenchで400弱ですので。
クエリを大量発行してテスト
まずは、どれくらい重いクエリに耐えられるかという基準を見たいので、単純にSELECTするだけのクエリをn回実行するテストをしてみました。
SQLiteのINSERTやUPDATEはデッドロック問題があるので、極力WEBサービスの本番では使わないほうが無難なので、テストしてません。もし、INSERTやUPDATEが必要なWEBサービスなら素直にMYSQLにしたほうが幸せになれます(たぶん)。
テストコード
set_time_limit(1200000);
$this->benchmark->mark('code_start');
$num = 1;
$i = 0;
while($i < $num){
$this->DB1 = $this->load->database('default', TRUE, TRUE);
$this->DB1->select();
$this->DB1->from('table1');
$this->DB1->where('status = 1');
$data = $this->DB1->get();
$result = $data->result_array();
$i++;
}
$this->benchmark->mark('code_end');
echo $this->benchmark->elapsed_time('code_start', 'code_end');
なお、statusにはインデックスが張ってあります。
テスト結果
回数 | 1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 6回目 | 7回目 | 8回目 | 9回目 | 10回目 | 合計時間(平均) | 1回あたり(平均) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0.0151 | 0.0067 | 0.007 | 0.0091 | 0.0099 | 0.0108 | 0.0069 | 0.0072 | 0.0065 | 0.0081 | 0.00873 | 0.00873 |
10 | 0.0404 | 0.0572 | 0.0562 | 0.0488 | 0.0442 | 0.04 | 0.0415 | 0.0517 | 0.0493 | 0.0509 | 0.04802 | 0.004802 |
50 | 0.1792 | 0.2072 | 0.2125 | 0.1928 | 0.2104 | 0.1973 | 0.2157 | 0.2108 | 0.2365 | 0.1978 | 0.20602 | 0.0041204 |
100 | 0.3622 | 0.4093 | 0.3888 | 0.3629 | 0.4208 | 0.3641 | 0.4121 | 0.436 | 0.3823 | 0.3965 | 0.3935 | 0.003935 |
1000 | 3.5201 | 2.9524 | 3.063 | 3.1081 | 3.1574 | 3.2899 | 3.0568 | 3.4788 | 4.1001 | 3.1466 | 3.28732 | 0.00328732 |
10000 | 39.628 | 36.6413 | 36.5627 | 29.4827 | 34.1682 | 35.1158 | 34.1765 | 31.4448 | 42.4125 | 38.9293 | 35.85618 | 0.003585618 |
概ね、1クエリあたり0.003-4秒くらいと考えて良さそうですね。これくらいの速度が出てくれるなら、本番運用もできるかもしれません。
Apache Benchで負荷テスト
上記のテストは複数クエリを同時に発行した時のテストだったので、次はどれくらいのアクセスを捌けるのかを見るために、Apache Benchを使って負荷テストをしてみます。
1ページあたりに発行されるクエリは、記事一覧などなら50回くらいだと思うので、上記のプログラムを$num=50にセットしてテストします。
テストコード
テストコードは下記の通り。
ab -n 総リクエスト数 -c 人数 http://localhost/
※Dockerコンテナ内で実行します
Apache Benchのテストは、人数 x リクエスト数なので、人数を「10、50、100、250、500」の4パターン、リクエスト数を「それぞれ1PV、10PV、20PV」の3パターン、合計15パターンでテストしてみました。
テスト結果
テスト結果です。以下の表は右下に行くほど負荷が高いようになっています。
※数字は、1ページを表示するのに掛かった時間(sec)
人数 | 1 リクエスト | 10 リクエスト | 20 リクエスト |
---|---|---|---|
10 | 0.167722 | 0.168007 | 0.159569 |
50 | 0.169482 | 0.17029 | 0.194768 |
100 | 0.171719 | 0.206688 | 0.207012 |
250 | 0.203337 | 0.213868 | 0.234238 |
500 | 完了できず | 完了できず | 完了できず |
おおよそ0.2秒以内、1秒あたり5リクエストというイメージですね。ちなみに、500人のパターンは、1人1リクエストでも処理が落ちてしまいました。
先ほどのテスト結果だと、50クエリの平均処理時間は0.2秒ほどだったので、ほぼ劣化しないか、むしろ速くなっています。多分同じクエリを発行しているからでしょう。
1秒で5リクエスト捌けると、
5 * 60秒 * 60分 * 24時間 * 30日 = 12,960,000PV
で、月間1300万PVほどを捌ける感じになります。実際にデータが増えたり、重い処理が入ったりして速度が1/4になったとしても、1リクエスト0.8秒ほどで捌ければ、月間300万PVくらいまで耐えられます。
これくらいのアクセスがあったら、少し高性能なサーバーを借りてもお釣りがくるはずなので(収入モデルがある場合はですが・・・)、アクセス負荷については当分気にしないで良さそうです。
こういうベンチマークはあくまで参考で、実際に開発を進めると「ベンチは速かったのに、動かしたら遅くない?」となりがちなので、あとはどのような効率の良いコードを書けるかによるかと思います。スロークエリが数個あるだけで、どんどん負荷がたまっていきますしね。
ただ、「おもちゃ程度」と言われるSQLite3ですが、単純に表示するだけのWEBサイトなどだったらかなりの負荷に耐えられることがわかったのは、個人的に収穫でした。
以上、CodeIgniter + SQLite3環境でのベンチマークテストでした。