TL;DR
- Rust/tokioで非同期チャットサーバーを作ってみました。
- 比較のために、同期サーバー作ってみました。
- テストしてパフォーマンスを比較しました。
- 思った通り、非同期の方がCPU負荷が少なく、同じ処理を実行できました。
- ついでに、C#でも非同期サーバーを実装して、比較しました。
- Rustの方が速そうでした。
※若干説明が正確でないところがあります。正しい理解のためには、公式ドキュメントなど参照してください。
Rustとは
- GCなしで、安全なメモリ管理
- 実行時コストなしで、抽象化
- 関数型言語からの影響
「プログラミング言語「Rust」は、「C」や「C++」並みのパフォーマンスと、開発者が墓穴を掘るのを防ぐ仕組みとを兼ね備えたプログラミング言語だ」
「プログラミング言語「Rust」--2019年こそ学ぶべき7つの理由」
https://japan.techrepublic.com/article/35131764.htm
Tokioとは
スレッドプールを使って、タスクを並列にいい感じに実行してくれるやつです。
※半年ほど前に作ったので、std::futureが入る前の古い方のtokioです。
tokio = "0.1.20"
futures = "0.1.25"
Tokioを使って非同期なチャットサーバーを作ってみよう
設計はこんな感じ。
送受信と入室処理がそれぞれ別タスク(別スレッド)で動く。
Channelとは、スレッドセーフなキューだと思ってもらえればOKです。
比較のために、同期のチャットも作ってみる。
設計はこんな感じ。
送受信も入室処理も全部同じタスクで処理。
何もすることがない時は、ループがぐるぐる回る。
パフォーマンス測定
- 50人が同時にアクセス
- サーバーは、1部屋10人ずつでルームを作る
- CLはそれぞれ、10〜100ミリ秒ずつランダムに間を開けながら、20〜200バイトのデータを繰り返し送信
結果:同期の場合
CPU使用率が上がったり下がったり。誰も喋っていない時、ループをぐるぐる回っているので、その間CPUが100%になっている
結果:非同期の場合
いい感じにCPU使用率が安定している。計画どおり ( ̄ー ̄)ニヤリ
C#で非同期もやってみた
CPU使用率はRustと同じくらい。でも、ネットワークの速度がRustより半分くらい遅い。
やっぱりRustは速い!ということに違いない。
わかったこと
- 非同期の方がCPUを効率よく使える(あたりまえですが・・)
- C#よりRustで書いた方が速度が出る
C#は async/awaitが使えるので非同期も簡単に書ける。
Rustももうすぐ async/awaitが来るので期待大。
Rustを使って良かったところ
- トレイトを使ってソケットの送受信の機能を抽象化。Room側のソースはTCP/WebSocket を意識しないで書ける。しかも抽象化による実行時コストがゼロ。
- Futureトレイトを使うことで、タスクが書きやすい(でも async/await があればもっと書きやすくなるはず)
Rustを使ってつらかったところ
- Future使った時に型推論がどう動くのかが理解できずに苦しんだ
- ドキュメントがあまり整備されてない
- サンプルが少ない
今回つかったソース
サーバー:
https://github.com/mas-yo/rustgs/tree/lt20190605
テストクライアント:
https://github.com/mas-yo/rustgs-testcl/tree/lt20190605