Sashimi開発日記 - 実態に近いベンチ結果

実態に近い機能(DBアクセス→キャッシュ処理→Markdownパース→テンプレートレンダリング)の実装が終わったのでベンチを改めて取りました。おそらく、今後機能拡張していってもここから劇的に(例えばひと桁とか)パフォーマンスが落ちることはないと思います。

ベンチ結果(wrk)

$ wrk -t12 -c400 -d30s http://localhost:9001/post/test
Running 30s test @ http://localhost:9001/post/test
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     6.64ms    0.96ms  26.09ms   89.81%
    Req/Sec     5.00k   568.71    37.94k    99.25%
  1790835 requests in 30.10s, 1.89GB read
Requests/sec:  59499.40
Transfer/sec:     64.29MB

ベンチ結果(apache bench)

$ ab -n 1000000 -c 18 http://localhost:9001/post/test

Server Software:        
Server Hostname:        localhost
Server Port:            9001

Document Path:          /post/test
Document Length:        1006 bytes

Concurrency Level:      18
Time taken for tests:   45.188 seconds
Complete requests:      1000000
Failed requests:        0
Total transferred:      1128000000 bytes
HTML transferred:       1006000000 bytes
Requests per second:    22129.83 [#/sec] (mean)
Time per request:       0.813 [ms] (mean)
Time per request:       0.045 [ms] (mean, across all concurrent requests)
Transfer rate:          24377.39 [Kbytes/sec] received

考察

abとwrkでかなり結果が違いますね。wrkの方が後発で、より並列処理に適した負荷のかけかたをしてる?みたいなので、wrkの方が正しい値と言えるでしょう。
両者で並行処理数のパラメータが異なっていますが、これはabではある程度同時実行数を上げてやらないとパフォーマンスが出なかったからです。

すると、Sashimiのパフォーマンスは約60k reqs/sということになります。同マシンで実行したwordpressは35 reqs/sでしたから、約1700倍ですか。

WordPressでここまでのパフォーマンスを出すとなるとフロントエンドでキャッシュさせるしかありませんが、これはプラグインが正常に動かなくなるなどの問題が多発します。当ブログでも一時期はそのようにしていましたが、あまりにも問題が発生するのでキャッシュを外した経緯があります。

フロントエンドでキャッシュする以外のキャッシュプラグインはそもそも効果の点でいまひとつで、非キャッシュ時の数倍程度の性能にとどまります。

image from Benchmarking the Fastest WordPress Cache Plugins

これはIO以外の処理時間もIOに匹敵する程度の大きさであることを示しています。PHPのパフォーマンス改善については全く知見が無いので分かりませんが、実行時コンパイルされたコードをHHVMで実行させても大したパフォーマンス向上にならなかった(実体験やベンチスコアをググった結果)ことを考えると、もうちょっとパフォーマンスが出せる言語を使って作り直すしか無いんじゃないかなという気がします。

フルキャッシュ状態でのベンチ結果(wrk)

以下はテンプレートを適用した結果(レンダリング結果)をキャッシュした場合です。つまりHTTP Responseのbodyに相当する情報をキャッシュします。

$ wrk -t12 -c400 -d30s http://localhost:9001/post/test
Running 30s test @ http://localhost:9001/post/test
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.49ms    4.71ms 208.89ms   99.21%
    Req/Sec    27.21k     3.85k   75.03k    94.66%
  9734596 requests in 30.10s, 10.27GB read
Requests/sec: 323406.16
Transfer/sec:    349.44MB

すると、323k reqs/sとまた一桁性能が向上します。秒間32万リクエスト。Yahooの地震速報で秒間数万アクセスくらいらしいです。ここまで来ると実用上は多分ネットワークがボトルネックになるはずなので、アプリが提供するパフォーマンスとしては十分なレベルで、ボトルネックになることは無いと思われます。

ちなみに、この結果はnginxでfastcgi cacheするよりも早いはずです。あれの実装はキャッシュデータをディスクに書くようになっています(はず)が、SashimiのキャッシュはCaffeine(オンメモリキャッシュ)なので。

Sashimiの機能としてはキャッシュのレベル(どの段階でキャッシュするか)とキャッシュの生存時間、トリガによるキャッシュの消去などの設定をサポートする予定ですが、デフォルトではすべてのキャッシュは有効になっているようにしたいと思います。

以前の記事で「ブログは動的な要素が意外に多いからキャッシュは解決策にならない」と書いたのですが、Sashimiでは動的に変更される部分は基本的にAjaxで更新されるものとして、記事本文までを高速に表示させることを重視する設計としたいです。

そもそもブログ(CMS)で動的に更新される部分は

  • SNSのシェア数
  • コメント
  • 広告

などでどれもすぐに表示されなくて良いものばかりです。そもそもSNSのシェア数(とアイコン)や広告は元々外部のAPIをajaxで叩くのが普通です。

コメントはCMSのシステムに包含されているケースが多いと思いますが、Sashimiではコメントもajaxによって制御するようなプラグインとして提供する設計にしたいと思います。というか、私がコメント機能は要らないと思ってるので開発する意欲がそもそもあんまり無かったりするのですが…。