embulk-output-oracleのパフォーマンスを向上する!
背景
ここでも書いたが、embulk-output-oracleを業務システムで使うには、もう少し速くしたい。
そこで、embulk-output-oracleのパフォーマンスを向上することにした!
embulk-output-oracleの現状のパフォーマンス
まずは、現状(embulk 0.8.12 + embulk-output-oracle 0.6.1 + embulk-input-filesplit 0.1.3)のパフォーマンスを確認しておく。
AWS上で以下の2つの環境で確認した。なお、OSはWindows 2012 Serverである。
No. | Oracle | Client | 入力データ |
---|---|---|---|
1 | c3.xlarge (4 vCPU, Magnetic disk) | c3.xlarge (4 vCPU, Magnetic disk) | 50,000,000レコード (10GB) |
2 | c3.2xlarge (8 vCPU, SSD) | c3.2xlarge (8 vCPU, SSD) | 200,000,000レコード (40GB) |
計測結果は、以下の通り。
なお、比較のため、名前は言えないが高速な某ツールでも計測している。
ちなみに、環境は異なるが、以前は某ツールより2割ほど遅かった。
[環境1]
ツール | 時間 |
---|---|
某ツール | 11.1m |
embulk-output-oracle + embulk-input-filesplit | 11.2m |
[環境2]
ツール | |
---|---|
某ツール | 10.6m |
embulk-output-oracle + embulk-input-filesplit | 22.0m |
現状のパフォーマンスに関する考察
環境2の方が4倍も入力が多いのに、時間があまり変わらないのは、SSDのおかげだ。
実際、環境1でも2でも、ディスクI/Oがかなり高負荷になっていた。
環境1では、embulkは某ツールと同じくらいだが、環境2では倍も時間が掛かっている。
つまり、環境1ではディスクが遅いためOracle側がボトルネックになっているが、環境2ではembulk側がボトルネックになっている。
改善せねば!
embulk-output-oracleのパフォーマンス改善
いろいろと計測したり分析したり試行錯誤した結果、修正したのは以下の2点。
なお、プルリクエストまでは作成したが、まだマージはされていない。
ネイティブライブラリ呼び出し回数を減らす
embulk-output-oracleは、Oracleのネイティブライブラリを利用することにより高速化している。
しかし、Java→ネイティブライブラリの呼び出し回数が非常に多いため、オーバーヘッドが大きくなっていた。
そこで、embulk-output-oracleとOracleライブラリの間に挟むネイティブライブラリを開発し、呼び出し回数を減らした。
詳細はこちら。
ロード処理回数を減らす
embulk-output-oracleの中の挙動をよく調べてみると、Oracleライブラリによるロード処理は約200レコード毎に行われていた。
これだとロード回数が非常に多いため、オーバーヘッドが大きくなっていたようである。
そこで、Oracleのネイティブライブラリのバッファサイズを大きくしたりして、ロード間隔をうまいこと調整するようにした(いろいろな条件によって変わるが、環境2の場合は4,000レコード毎くらい)。
embulk-output-oracleのパフォーマンス改善結果
改善版を使って、パフォーマンスを計測してみた。
タスク数(並列数)を変えたり、embulk-input-filesplit無しでも測ってみた。
[環境1]
ツール | 時間 | |
---|---|---|
某ツール | 11.1m | |
embulk-output-oracle + embulk-input-filesplit | 4タスク | 11.3m |
2タスク | 11.3m | |
1タスク | 12.2m | |
embulk-output-oracleのみ | 11.5m |
[環境2]
ツール | 時間 | |
---|---|---|
某ツール | 10.6m | |
embulk-output-oracle + embulk-input-filesplit | 8タスク | 10.1m |
4タスク | 10.9m | |
2タスク | 20.1m | |
1タスク | 36.7m | |
embulk-output-oracleのみ | 25.6m |
環境1の方は、Oracle側が非力なので、どれで測っても大差ない。
さすがに1タスクだとちょっと遅くなるが。
環境2の方は、パフォーマンス改善の効果が顕著に出ている!
4タスク以上であれば某ツールと互角だ。
embulk-input-filesplit無しの場合、出力タスクは並列化されるが、入力タスクが並列化されないため、パフォーマンスが落ちるのだろう。
まとめ
もちろん、環境やテーブル設計にもよるので一概には言えないが、embulk-output-oracleが某ツールと互角のパフォーマンスを出せたのは非常に嬉しい結果である。
他の環境(より高性能な環境とか、高いが…)でも計測してみたい。
と言うか、早く実システムでも使ってみたい!