はじめに

こんにちは。ブロックチェーン推進室の鈴木です。

私の所属するブロックチェーン推進室では、企業間取引に特化したエンタープライズブロックチェーンプラットフォーム:Cordaに関して機能調査を行っております。
Cordaは世界で350社を超える金融機関、規制当局、中央銀行、業界団体、システム・インテグレーターやソフトウェアベンダーにより構成されるR3エコシステムから、エンドユーザー目線で設計・開発されています。
また、4半期に1度のバージョンアップにより機能追加がされていますが、その機能がお客様に活用できるものなのか、ドキュメントだけではわからないことも多く、ブロックチェーン推進室独自で調査を進めています。

このブログでは、そういったCordaの機能調査をした結果を機能の使い方含めて紹介していきます。

Cordaの導入方法についてはこちらのドキュメントをご参照ください。

今後以下の内容で紹介しようと思います。

  1. Corda JMeterの使い方

  2. Corda Enterprise Performance検証 ノードスペックを変化することによる性能変化(←今回はこちらの記事)

  3. Corda Tokens SDK and Accounts

  4. Corda Enterprise Collaborative Recovery

  5. Corda Enterprise Archive Service

  6. Corda Firewallの設定方法

  7. Corda re-issuance Tokens SDK and Accountsを利用した一括「re-issuance」

  8. Corda Time-windows

  9. Corda Oracle

  10. Corda attachment

  11. Corda Webアプリケーション開発について

  12. Cordaを用いたNonFungibleTokenの実装

  13. CordaのTokens SDKでNFTマーケットプレイスを作ってみた

(以降、バージョンアップの都度、新機能を紹介予定)

第2回目は「Corda Enterprise Performance検証 ノードスペックを変化することによる性能変化」について紹介します。

導入

前回はCorda JMeterの設定及び実施方法について紹介いたしました。
これでパフォーマンステストは実施できます。Corda Enterpriseでは、マルチスレッドでの処理を可能にしており、スレッド数を多くするとTPSの向上が見込めます(※)

サーバスペックを変えるとどのように性能が変化するか、またCorda内で持つ設定変更による影響はどの程度あるのか、実際に検証しましたので、紹介いたします。

※ 1トランザクションを1秒で完了できるが、1つしか実行できない場合、1TPSとなる。1つのトランザクションは2秒かかるが、同時に2つ実施できる場合、これも1TPS。仮に4つ実施した場合、2TPSとなる。Cordaは後者のように同時処理数を多くすることでTPSを向上させている。

実施前提

  • Corda Enterprise4.3を利用します。(2021年9月時点で最新版は4.8)
  • ノードは3台(NodeA、NodeB、Notary、CENMはNotaryと相乗り)

今回検証したシステム構成イメージ

  • 実施したFlow
    • Create:自ノードに対して発行を実施します。Notaryは関与しません。
    • Send:他ノードに送信します。Notaryが関与します。
  • ノード用RDBはPostgreSQLを利用し、各ノードに相乗りさせています。DBにもパフォーマンステストケースに応じて設定変更をしました。

【DB設定変更】

設定変更ファイル/var/lib/pgsql/9.6/data/postgresql.conf内のmax_connectionsを変更します。

デフォルトは100です。「FlowThreadPoolSize +1以上」が望ましいとされているが、大きくしすぎるとメモリ消費量が増えます。

Cordaの仕様として、ノードの起動時に「FlowThreadPoolSize + RPCThreadPoolSize + α」のコネクションを張るため、「(FlowThreadPoolSize+RPCThreadPoolSize)*1.1」程度が落とし所と判断しています。

※起動時に確保するので、もし足りないとノード自体が起動できずエラーとなりますので、注意が必要です。

・初回実施が遅くなるため、パフォーマンステスト実施前に必ず1シナリオ実施しておく必要があります。

上記、実施前提のもと、以下のパターンでパフォーマンステストを実施しました。

1.サーバスペックを向上させた場合の性能変化

2.Cordaの設定値ThreadPoolSizeのみの変更

3.JavaHeapサイズの変更

4.vCPUを32にした場合の性能変化

上記の実施内容と実施結果について記載いたします。

実施内容1 ノードスペックを向上させた場合の性能変化

AWS EC2のインスタンスタイプを変更し、併せて同時処理実施を可能とするCordaの設定「ThreadPoolSize」を変更して、パフォーマンステストを実施しました。
ThreadPoolSizeにはFlowThreadPoolSizeとRPCThreadPoolSizeがあります。以降の説明ではそれぞれflow、rpcと略して記載いたします。

実施内容1 AWS EC2のインスタンスタイプを変更

表のように、vCPUを2倍ずつ上げていき、併せてThreadPoolSizeも変更しました。flowの設定値はvCPUの4倍、rpcの設定値は2倍とすることがR3社の推奨設定値となっています。

実施結果1

実施結果1 赤枠の「結果(TPS)」参照

上記表の通り、vCPUを上げるとそれに合わせて、TPSも向上しています。

FlowのSENDのほうは、倍にしていくと、おおよそ倍近く向上していますが、CREATEのほうは倍までは向上していませんでした。これについての考察は実施結果4.に記載します。

実施内容2 Cordaの設定値ThreadPoolSizeのみの変更

vCPU関係なく、ThreadPoolSizeに応じて挙動するかを確認する為、AWS EC2のインスタンスタイプはそのままにして、ThreadPoolSizeのみ変更させた場合のパフォーマンステストを実施しました。

実施内容2 ThreadPoolSizeの変更

No.6~No.8までは単純にThreadPoolSizeを増加させたもの、No.9およびNo.10は逆に小さくしたもので検証いたしました。

実施結果2

実施結果2 赤枠の「結果(TPS)」参照

上記の表の通り、ThreadPoolSizeを増加させても、若干の誤差はありますが、vCPUが8の時のThreadPoolSize推奨値以上の大きな性能はでないことが分かりました。
大きくしすぎた場合、数値が下がっていることもあるため、推奨値を設定することがベストだと思います。
逆に小さくした場合、No.9ではrpcを1としていますが、SENDの数値は極端に悪くなっていない為、RPC側の設定を極端に少なくしてもあまり影響がないと言えます。
逆にNo.10では、Flowの実施件数そのものが低くなるため、CREATE、SENDも少なくなっており、flowの設定には推奨値以下の場合は影響が出るということが言えます。

実施内容3 JavaHeapサイズの変更

CordaはJava環境で動作するため、JavaHeapサイズを変更して、パフォーマンステストを実施しました。

実施内容3 JavaHeapサイズの変更

No.11では、JavaHeapを8GBの2倍の16GBに設定し、No.12では8GBの半分である4GBに設定しました。

実施結果3

実施結果3 赤枠の「結果(TPS)」参照

上記の表の通り、倍にしたNo.11では、性能に大きな差はなく、逆に少なくすると、若干ではあるものの、性能が悪くなることが分かりました。
チューニングする場合は、あまり小さすぎず、大きくしても性能差がないため、大きくしすぎないことがポイントと言えます。

実施内容4 vCPUを32にした場合の性能変化

R3社のCordaの「Performance benchmarking results」図3を見ると、32コアでIssue(ここでいうCREATE)が1001TPS出ています。実際1000TPSが我々の環境でも記録できるかを確認しました。

実施内容4 vCPUを32にして様々な設定値を変更

32コアのまま、ThreadPoolSizeやJavaHeapを変更し、CREATEが1000TPS出るかを検証しました。

実施結果4

実施結果4 赤枠の「結果(TPS)」参照

上記の表の通り、結果としては1000TPSまでは記録できませんでした。(1000TPS出るまでやり続けたので試行回数が多くなってしまいました)

我々の環境では、各ノード内サーバにDBを相乗りさせていることでOSのI/O等でボトルネックとなり、1000TPSまで行きつかなかったのが原因と推測されます。
R3社の実証では、各ノードとDBは別サーバで立てている為、我々の環境もそのような構成にすれば、もう少し1000TPSに近づけた可能性があります。

まとめ

今回はCorda JMeterを利用し、ノードスペックを変えるとどのように性能が変化するか、またCorda内で持つ設定変更による影響はどの程度あるのかを実際に検証しました。
実施した結果としてまとめると以下になります。

  1. ノードのスペックを上げれば、処理性能も向上する。
  2. Flow/RPC ThreadPoolSizeを変更すると、処理性能も変化するが大きくしすぎても逆効果であるため、R3社推奨値のFlow:vCPUの4倍、RPC:vCPUの2倍にするのがよい。
  3. Java Heapの影響は少ないが、小さすぎても大きすぎてもいけない為、OSメモリの1/4~1/2くらいがよい。
  4. DBがボトルネックとなることもあるため、性能向上にはDBは別サーバにて専用で用意することが望ましい。

最後に

今回の結果を見て、お気づきの方もいらっしゃるかもしれませんが、R3社推奨値のFlow:vCPUの4倍、RPC:vCPUの2倍にした際、

CREATE:自ノードに対して発行を実施する。Notaryは関与しない。

SEND:他ノードに送信する。Notaryが関与する。

というFlowを実施すると、SENDについてはCREATEの約20%のTPSしか出ていないということです。これは、R3社の「Performance benchmarking results」でも同じ結果となっています。
SENDについては、他ノードの検証や署名とNotaryノードの署名があり、どうしても遅くなります。
その性能はCREATEの1/5ということを念頭においてください。(他ノード1つ+Notary の場合です。他ノードが複数だとVer4.3では更に処理が遅くなります。)

パフォーマンステストを実施した際、TPSが出ない場合は検証したFlowはSENDなのかどうかを確認し、もしSENDならCREATEで5倍くらいの数値が出るか、もし出ない場合は設定値が最適になっているか等を確認してください。

ちなみに、CordaのOSS版やデータベースをH2DBにしていた場合、ここまでのTPSは出ません。TPSを向上させたい場合は、Corda Enterpriseと、MySQLやOracleDB、PostgreSQLなどのRDBMS製品を利用してください。

本検証について繰り返しになりますが、改めてまとめますと

  1. 本検証ではVer4.3を使っていて、最新版ではない。
  2. 各ノードで同じサーバにDBを乗せている為、I/Oがボトルネックとなっている。
  3. サーバのスペックが高いほど処理性能は向上している。
  4. 性能向上のためにはDBを別サーバに用意することが望ましい。
  5. OSS版のCordaやH2DBを使用していた場合、これほどのTPSは得られないので,CordaEnterpriseやMySQL、OracleDB、PostgreSQLなどのRDBMS製品を使用するべきである。
  6. 本検証における数値は、TISがR3の提供するパフォーマンスチューニングのアドバイスを受けずに作成したものであり、R3社の「Performance benchmarking results」のサイトを見ると、issue(今回でいうCREATE)で 2580TPS、issue&pay(今回でいうSEND)で 617TPSを実現している。

以上です。