おくみん公式ブログ

おくみん公式ブログ

Influent ベンチマーク - Part 1 #fluentd

f:id:okumin:20170124002659p:plain

Java 版 Fluentd サーバである、Influent のベンチマークを取ってみました。今回は第一弾で、今後も性能を改善しながら、都度ベンチマーク結果を載せていく予定です。

テスト概要

fluentd-benchmark を用いて Fluentd 及び Influent へ負荷をかけます。これは dummer で生成したイベントを Fluentd エージェントで大量に送りつけるもので、fluent organization のものをほぼそのまま用いています。

受信サーバの処理は、受信したイベントの数を1秒ごとに標準出力に書き出すという単純なものです。Fluentd のテストには上記の fluentd-benchmark に同梱されている設定を用います。Influent のテストには同じような処理を行うこちらのアプリケーションを用います。

Disclaimer

Fluentd と Influent の比較について

この記事は Fluentd のベンチマーク結果を Influent のベンチマーク結果に併記しています。ただし、この結果をもとにどちらの性能が優れているかを推し量ることはできない、という点に留意してください。

Influent は Fluentd が持つ機能のいくつか、例えばルーティング機能のようなものを提供していません。そのため、直接比較すると Fluentd に不利な結果となるでしょう。また次に述べるように Fluentd の性能を引き出しきれている保証もありません。

Fluentd のベンチマーク結果について

本記事に記載している Fluentd のベンチマーク結果は、本来の性能を発揮できていない可能性があります。理由は、私が Fluentd や Ruby のパフォーマンスを引き出す術に明るくないからです。

サーバのセットアップ方法やベンチマークの実行方法は influent-benchmark により管理されているので、よりよいテスト方法をご存じの方は PR してくれると嬉しいです。

テスト環境

サーバ

送信サーバ及び受信サーバには、Google Compute Engine asia-northeast1 リージョンの n1-highcpu-32 を用いました。

送信サーバ一台だと負荷をかけきれないケースがあるので、送信側は二台用意しました。それぞれ20プロセスの Fluentd が並列にイベントを送信します。

バージョン

環境構築は influent-benchmark の 78828a54a18783f5b976935e3df33aa709164a6d で行いました。

Fluentd のバージョンは 0.12.31 で、Influent のコミット ID は f38aa35ca708a72df66f07b5e87a43a0b24eb3ef です。

プロトコル

Fluentd 0.12 を用いて、at-most-once(require_ack_response なし)プロトコルでイベントを送信しました。at-least-once でも軽く試しましたが、Fluentd がそれなりの数のイベントをバッファリングしつつ送っているからか、あまり結果は変わりませんでした。

テスト結果

ある程度負荷をかけて安定したタイミングで、受信していたイベント数をアバウトに記録しました。また今回は CPU がボトルネックとなっていたので、CPU 使用率も載せています。

Influent のアプリケーションのうち、すごくアクティブなスレッドは1スレッドのみです。CPU 使用率が100%を超えている分はほぼ GC スレッドによる処理であると思われます。

Fluentd Influent
送信イベント数(秒) 受信イベント数(秒) CPU (%) 受信イベント数(秒) CPU (%) 備考
400000 400000 40~45% 400000 30~45%
600000 600000 60~65% 600000 40~55%
800000 800000 80~90% 800000 60~70%
1000000 800000~1000000 100% 1000000 70~90%
1200000 800000~950000 100% 1200000 85~100%
1400000 N/A N/A 1400000 100~115%
1600000 N/A N/A 1600000 125~145%
1800000 N/A N/A 1800000 95~155% テスト中に JVM のヒープサイズ拡張
2000000 N/A N/A 2000000 100~115%
2200000 N/A N/A 2000000~2150000 110~115%
2400000 N/A N/A 2000000~2150000 110~115%

雑感

Java で Fluentd の in_forward っぽいことをするライブラリを作りました』で予想していたとおり、シンプルな処理では大きな差が出ませんでした。プロファイリング結果によると、PackedForward の MessagePackEventStream をパーズする処理でかなりの CPU を使ってしまっているので、性能が劇的に改善することもなさそうな感じがしています。

とはいえ Influent は性能面の最適化をほとんどしていないので、後述する TODO を解決して、またベンチマークを取っていこうと思います。

TODO

MessagePack デコード処理の改善

msgpack-java はインクリメンタルなデコードができないので、パケットを受け取る度に毎回一から unpack しています。この部分がそこそこプロファイリング結果に出てきていたので、ストリームデシリアライザを実装しようと思っています。

マルチスレッド対応

現状 Influent のネットワーク処理〜MessagePack のデコード処理部分はシングルスレッドで動いています。一方ユーザーの処理(受け取ったイベントをどこかに送信するとか)はマルチスレッドで処理できるようになっています。この構成だと 10Gbps の線の上で、Influent がボトルネックとなってしまうことがほぼ確定しています。

次のバージョンの Fluentd にはポートを複数ワーカーで共有する機能(Symmetric multi process)が入るらしいので、Influent にも MessagePack のデコードをスケールする仕組みを導入したいです。

0.14 を使ったテスト

現在リリースされている Fluentd 0.14 はタグの送信フォーマットが仕様に沿っておらず、Influent で受け取れないので今回は 0.12 のみを使ったテストとなりました。Fluentd 0.14 自体の性能にも関心があるので、特に Symmetric multi process 機能が入ったらまた比較してみたいです。

より現実的なテストケース作成

Fluentd 本体がよくできている以上、Java の性能を活かせるのは、やはり重い計算を行う場合や、マルチスレッド処理、IO を伴う処理が必要な場合ではないかと考えています。fluentd-benchmark は若干シンプルよりなので、Google Cloud Pub/Sub に書き込むとか、そういうケースも試験できたらいいなと考えています。

関連リンク