Plamo対応、多言語対応、高性能Webサーバー、MonsterEngineをリリースしました
2020/01/15
MonsterEngineとは
MonsterEngineはPlamoに対応した多言語対応の高性能Webサーバーです。
Rubyで言うところのPumaみたいなやつです。
公式サイトは https://monsterengine.org
公式サイトのデザインは@kanaktに、英文の添削は@matsumoto4aにお願いしました。
本当はPlamoのリリース時に一緒に出したかったのですが、思った以上に時間がかかってしまい別々にリリースすることになりました。
実はRuby版にはいくつかバグがあるのですが、数日かけても直せなかったため一旦バグったままリリースして、後ほどコミュニティなどで質問してみることにしました。
Ruby版のバグ
Ruby版は現在以下の2つのバグがあります(ただこの2つのバグはRuby版のMonsterEngineではなくRuby版のPlamoのバグの可能性があります)
- GCを無効化しないとセグフォで落ちる
- 同時にアクセスがあると稀にハングアップしてしまう
パフォーマンス
MonsterEngineよりPumaのほうが多機能だったりして単純な比較はできないですが、簡単なベンチマークをとってみました。
Ruby版にバグがあるためGCを無効化、h2loadのクライアント数を1に設定してベンチマークを5回とって一番結果の良かったものが以下です(条件を同じにするためPumaの方もGCを無効化しています)
$ # Puma(ruby: 2.7.0, puma: 4.3.1)デフォルトだと標準出力にログが出力されるのでログ出力を無効化しています
$ h2load -c 1 -n 10000 -p http/1.1 http://localhost:8888
starting benchmark...
spawning thread #0: 1 total client(s). 10000 total requests
Application protocol: http/1.1
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 2.96s, 3378.32 req/s, 293.62KB/s
requests: 10000 total, 10000 started, 10000 done, 10000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 10000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 869.14KB (890000) total, 439.45KB (450000) headers (space savings 0.00%), 68.36KB (70000) data
min max mean sd +/- sd
time for request: 235us 1.10ms 295us 31us 81.98%
time for connect: 104us 104us 104us 0us 100.00%
time to 1st byte: 746us 746us 746us 0us 100.00%
req/s : 3378.56 3378.56 3378.56 0.00 100.00%
$ # Ruby版MonsterEngine(ruby: 2.7.0, monster_engine: 0.1.0)
$ h2load -c 1 -n 10000 -p http/1.1 http://localhost:8888
starting benchmark...
spawning thread #0: 1 total client(s). 10000 total requests
Application protocol: http/1.1
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 447.16ms, 22363.51 req/s, 1.75MB/s
requests: 10000 total, 10000 started, 10000 done, 10000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 10000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 800.78KB (820000) total, 468.75KB (480000) headers (space savings 0.00%), 68.36KB (70000) data
min max mean sd +/- sd
time for request: 34us 464us 44us 10us 94.05%
time for connect: 98us 98us 98us 0us 100.00%
time to 1st byte: 569us 569us 569us 0us 100.00%
req/s : 22370.88 22370.88 22370.88 0.00 100.00%
$ # Rust版MonsterEngine(rust: 1.40.0, libmonsterengine: 0.1.0)libmonsterengineを直接Rustから使ってる
$ h2load -c 1 -n 10000 -p http/1.1 http://localhost:8888
starting benchmark...
spawning thread #0: 1 total client(s). 10000 total requests
Application protocol: http/1.1
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done
finished in 227.54ms, 43947.54 req/s, 3.44MB/s
requests: 10000 total, 10000 started, 10000 done, 10000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 10000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 800.78KB (820000) total, 468.75KB (480000) headers (space savings 0.00%), 68.36KB (70000) data
min max mean sd +/- sd
time for request: 19us 163us 22us 6us 91.61%
time for connect: 104us 104us 104us 0us 100.00%
time to 1st byte: 273us 273us 273us 0us 100.00%
req/s : 43976.26 43976.26 43976.26 0.00 100.00%
機能が違う上にバグの関係でGC無効化やクライアント数制限などをしているので単純な比較はできませんが、PumaとRuby版MonsterEngineだとRuby版MonsterEngineのほうが6倍以上高速なようです。
Ruby版MonsterEngineとRust版MonsterEngineで思っていたほど差がないのには驚きました。
ToDo
未実装の機能の中で大事そうなものだとGraceful Restartがあります。
これは次のアップデートで入れられたらと思っています。
お試しDocker
現状Linuxでしか動かないため環境構築が面倒だと思うのでRuby版のお試し用Dockerfileを用意しました(ベンチマークを取る場合は条件を合わせるためMonsterEngineじゃない方もDockerで動かしてください)
- 以下をコピーしてファイル名
Dockerfile
で保存 $ docker build -t monster_engine_example .
でDockerイメージを作成$ docker run --rm -it -d -p 8888:8888 monster_engine_example
- ポート8888にリクエスト(例:
$ curl 'localhost:8888'
)
FROM archlinux:20200106
ENV LANG C.UTF-8
RUN pacman -Sy --noconfirm ruby ruby-bundler rust make gcc git
RUN git clone https://github.com/plamo/libplamo.git /usr/local/src/libplamo
RUN git clone https://github.com/monsterengine/libmonsterengine.git /usr/local/src/libmonsterengine
RUN cd /usr/local/src/libplamo && make && make install
RUN cd /usr/local/src/libmonsterengine && make && make install
RUN git clone https://github.com/monsterengine/monster_engine_ruby.git /usr/local/src/monster_engine_ruby
RUN cd /usr/local/src/monster_engine_ruby && bundle install && bundle exec rake build
WORKDIR /usr/local/src/monster_engine_ruby
EXPOSE 8888
CMD ["./bin/monster_engine"]
最後に
Plamoだけだとただの抽象化レイヤーでしかないので今までは試すことも難しかったと思いますが、今回MonsterEngineをリリースしたことで手軽にPlamoを使えるようになったので、ぜひ一度試してみてください!🙇