parity-ethereumのベンチマーク
こんにちは、次世代システム研究室のN.O.です。
Z.com Cloud ブロックチェーンではブロックチェーン技術にEthereumを利用しています。Ethereumではgeth(Go Ethereum)やparity-ethereum(Parity Ethereum)、以前の記事でご紹介したEthereum Harmonyなど、様々なクライアントがあります。クライアントを選択するにあたり、ベンチマークを比較することがあると思います。
今回は、手軽に複数のクライアントのベンチマークが実施できるツール、Chainhammerを使ってgethとparity-ethereumを比較し、結論としては同様のベンチマーク結果が得られたのですが、その過程でparity-ethereumのチューニングについて詳しく知ることができたので、共有したいと思います。
Chainhammerを使ってみる
まずはChainhammerを使ってみたいと思います。環境は以下を使用します。
- ConoHa
- プラン 4GB
- イメージタイプ Debian 9.7(64bit)
インストール
アップデートおよびgit、curlをインストールし、一度リブートを行います。sudo apt-get update sudo apt-get -y upgrade sudo apt-get -y install git curl sudo rebootclone後、インストールスクリプトを実行します。
git clone https://github.com/drandreaskrueger/chainhammer.git cd chainhammer ./scripts/install.sh正しくインストールされているか確認したい場合は、テストスクリプトを実行します。
./pytest.sh1件eth_utilsでDeprecationWarningが出ましたが、ベンチマークの測定に支障はありませんでした。
eth_utils/applicators.py:32: DeprecationWarning
ベンチマーク
Chainhammerでは以下のクライアント、およびエンジンをサポートしています。- TestRPC
- geth clique
- Quorum
- parity-etereum Instant Seal
- parity-etereum Aura
geth clique
CH_TXS=10000 CH_THREADING="threaded2 20" \ ./run.sh ConoHa4GB-Geth geth-cliqueparity-ethereum Aura
networks/parity-configure-aura.sh v1.11.11 CH_TXS=10000 CH_THREADING="threaded2 20" \ ./run.sh ConoHa4GB-ParityAura parity結果はresults/runs以下にhtml, markdownの形で出力されます。markdownの1行目にTPSが出ています。geth cliqueとparity-ethereum Auraでは以下の通りとなりました。
環境 | クライアント | エンジン | Tx数 | TPS (Tx Per Seccond) |
---|---|---|---|---|
ConoHa4GB | Geth v1.8.14 | clique | 10000 | 374.1 |
ConoHa4GB | Parity v1.11.11 | Aura | 10000 | 41.2 |
結果にだいぶ差がついてしまいました。この原因についてissueが上がっていますので、詳しく説明します。
Parityのチューニング
parity-ethereum AuraでTPSが出ない件については、Chainhammerの作者drandreaskruegerさんがissueを投稿し議論が続きました。最終的にparityの開発者tomusdrwさんのコメントによってparityでもgeth同様の結果が得られ、その再現手順が示されました。そのコメントによりますと、一番影響するのが
--fast-unlock
というフラグです。parityではセキュリティ上の理由から、Accountをunlockする際もパスワードのみメモリに保持し、生の秘密鍵は署名が終わったらすぐにメモリから消去します。このように署名のたびにAccountのkeyfileから秘密鍵をメモリにロードする方式のため、メモリの脆弱性をついた攻撃には耐性がありますが、その分ファイル読み込みが発生するため、パフォーマンス的に不利になります。--fast-unlock
ではunlockが無期限の場合に限りこの振る舞いを無効にし、秘密鍵をメモリに保持します。今回はベンチマークが目的なので、--fast-unlock
を有効にします。他にもいくつかチューニングの参考になるパラメータの説明がありました。
--gas-floor-target=40M
gas floor targetは、blockのgasLimitの下限です。blockのgasLimitは前のブロックのTx量によって決まります。前のブロックのTxが少なければgasLimitも減少していき、逆に前のブロックのTxが多ければ上昇します。普段Txが少ないネットワークでは下限になりがちなので、下限を適切な値にする必要があります。なおdefaultは8Mです。
--jsonrpc-server-threads 8
ベンチマークではマルチスレッド、非同期でTxを投げるので、受け側も適切なスレッド数にする必要があります。コメントでは
2*core
で算出した、とありました。ConoHa 4GBのVCPUは4なので、こちらも8を選択しました。defaultは4です。--jsonrpc-threads=0
上記のRPC serverに追加するthreadの数です。コメントには「最近のバージョンでは何もしない」とありました。threadを追加すると、thread間でdataのやり取りが発生し時間を消費します。このベンチマークではRPCのスループットはそこまで必要としないので、0にします。defaultは4です。
--tx-queue-per-sender 8192
送信者ごとのTx queueのサイズを指定します。ベンチマークでは単一の送信者がTxを送信するため、すべてのTx queueを割り当てます。(ちなみに、実社会のシナリオでは単一の送信者に多くのキューを割り当てる必要はありません。)defaultは
--tx-queue-size
(すべてのTx queue)の1%です。なお--tx-queue-size
のdefaultは8192です。--no-discovery
ノードが決まっている場合、ピアの探索は不要なので無効にします。
再びベンチマーク
以上を踏まえ、parityのオプションとunlockの期限を修正します。差分はこちらです
再度計測すると多少改善しましたが、それでもgethには及びません
環境 | クライアント | エンジン | Tx数 | TPS (Tx Per Seccond) |
---|---|---|---|---|
ConoHa4GB | Parity v1.11.11 | Aura | 10000 | 141.8 |
ログを眺めていると、トランザクション数が同じ数で頭打ちになっていました。
block 15 | new #TX 1492 / 10000 ms = 149.2 TPS_current | total: #TX 1493 / 10.8 s = 137.7 TPS_average (peak is 137.7 TPS_average) block 16 | new #TX 1492 / 10000 ms = 149.2 TPS_current | total: #TX 2985 / 21.3 s = 140.0 TPS_average (peak is 140.0 TPS_average) block 17 | new #TX 1492 / 10000 ms = 149.2 TPS_current | total: #TX 4477 / 31.5 s = 142.2 TPS_average (peak is 142.2 TPS_average) block 18 | new #TX 1492 / 10000 ms = 149.2 TPS_current | total: #TX 5969 / 40.8 s = 146.2 TPS_average (peak is 146.2 TPS_average)このときblockのヘッダを確認すると、gasUsedがgasLimitにひっ迫していることがわかりました。
curl -s --data '{"method":"eth_getBlockByNumber","params":["latest",true],"id":1,"jsonrpc":"2.0"}' \ -H "Content-Type: application/json" \ -X POST localhost:8545 | jq .result.gasLimit,.result.gasUsed "0x2625a00" "0x26119fc"gasはblockのgasLimitで制限されるので、これ以上Txが入らなかったのです。
この問題を解決するには、blockのgasLimitを増やすか、blockの間隔を短くすることです。今回はblockの間隔を5秒から3秒に変更しました。以下がその結果です。
環境 | クライアント | エンジン | Tx数 | TPS (Tx Per Seccond) |
---|---|---|---|---|
ConoHa4GB | Parity v1.11.11 | Aura | 10000 | 405.1 |
まとめ
今回はgethには手を入れていませんので、ベンチマークとしては不十分かと思います。(おそらくChainhammerである程度チューニングされていると思いますが、、、)またベンチマークでは簡単なケースしか試していないため、プロジェクトで採用する際はユースケースに合わせてシナリオを作成し、性能検証すべきです。ただ、今回の調査を通してparity-ethereumのパラメータについて深く知ることができたので、今後のチューニングに活かしたいと思います。
なお、今回パフォーマンス寄りにセッティングしましたが、
--fast-unlock
はセキュリティを考慮すると安易に有効にするべきではありません。バッチ処理等で大量にTxを送信する場合に、一時的に有効にする、ノードは使い捨てにする、といった使い方ならよいのではないかと考えます。