Solana RPCのsimulateTransactionが遅い原因と対処法

Solana の RPC エンドポイントで simulateTransaction が極端に遅くなったりタイムアウトを繰り返すのは、単純なリクエスト数の上限設定では根本的に解決できない。原因は Agave バリデータクライアントの実装にあり、少数の重いシミュレーション要求が実行スレッドを占有してすべての RPC 処理を巻き添えにする。

なぜ simulateTransaction だけが全体を遅くするのか

なぜ simulateTransaction だけが全体を遅くするのか

Agave(Solana の主要バリデータクライアント実装)では、simulateTransaction同期処理 として動く。これは、リクエストを受け付けるワーカースレッド(Tokio の共有スレッドプール)上で、トランザクションのシミュレーションが最後まで完了するまでそのスレッドを離さないことを意味する。

通常の RPC 呼び出し(残高照会やトランザクション送信など)は短時間で処理が終わるが、シミュレーションは複雑なコントラクト実行を伴うと数百ミリ秒から数秒に及ぶ。そのあいだ ワーカースレッドが占有され、他のすべての RPC リクエストが待たされる 状態になる。

さらに simulateTransaction はガス代(手数料)がかからないため、認証なしで何度でも呼び出せる。悪意がなくても、多数のウォレットやボットが短時間に大量のシミュレーションを投げれば、共有プール全体が簡単に飽和してしまう。

「リクエスト数制限」では防げない理由

「リクエスト数制限」では防げない理由

直感的には「1秒あたりのリクエスト数を制限すればいい」と思えるが、それでは不十分だ。問題はリクエストの「数」ではなく、ワーカースレッドを どれだけ長時間占有するか にある。

具体例を挙げると、solana-test-validator 2.2.16 で 8 つのワーカースレッドを用意した環境を想定する。シミュレーションが 1 スレッドを 5 秒占有する場合、同じ秒数で他の通常リクエストは数十件処理できる。IP ごとのリクエスト数上限は「回数」だけを見ているため、こうした 占有時間の偏りをまったく検知できない

実際の計測でも、8 並列で処理した場合のスループット向上はわずか 1.13 倍にとどまり、8 倍には遠く及ばなかった。同時に、ワーカーあたりのレイテンシ(応答時間)の中央値は 7.5 倍に悪化している。リクエスト数が少なくても、少数の重いシミュレーションが全体を引きずる構図だ。

どんな場面で問題が表面化するか

どんな場面で問題が表面化するか

この問題は特に次のような状況で顕著になる。

  • NFT ミント直前に複数のウォレットでトランザクションをシミュレーションしている
  • DeFi プロトコルの複雑な操作(レバレッジ調整や流動性の追加)を事前確認している
  • 取引ボットが高頻度でシミュレーションを走らせている
  • 無料の公開 RPC エンドポイントを多数のユーザーが同時に使っている

これらの場面では、シミュレーションを実行している本人だけでなく、同じエンドポイントを使うすべてのユーザーの RPC 応答が遅くなる。残高照会すら数秒待たされたり、最悪タイムアウトエラーになる。

自分で対処するための現実的な手段

自分で対処するための現実的な手段

ノード運営者側の対策(後述)はすぐに反映されるとは限らないため、利用者としてまず取れる手を押さえる。

専用 RPC サービスを使う

無料の公開エンドポイント(api.mainnet-beta.solana.com など)は最も混雑しやすい。Helius、QuickNode、Triton、Alchemy といった専用 RPC プロバイダーは、ユーザーごとに隔離されたワーカープールや専用ノードを提供しているため、他者のシミュレーションに引きずられるリスクが大幅に減る。

タイムアウトとリトライを適切に設定する

SDK やライブラリ(@solana/web3.js 等)で RPC 呼び出しを行う際は、タイムアウト値を明示的に設定する。デフォルトのまま使うと、シミュレーションが長時間ブロックされた際にアプリケーション全体が固まる。タイムアウト時はバックオフ(徐々に間隔を空けて再試行)を実装すると、ノード負荷の回復を待つ動きができる。

シミュレーション前に compute unit 上限を下げる

simulateTransaction に渡す maxComputeUnits(最大計算ユニット数)を必要最小限に設定する。無制限に近い値を指定すると、ノード側で長時間の実行を許してしまい、ワーカー占有がより深刻になる。ウォレットや dApp によってはデフォルト値が大きすぎる場合があるため、見直す価値がある。

独自のバリデータまたは RPC ノードを運用する

高頻度でシミュレーションを使うボットやサービスを運用しているなら、自分で RPC ノードを立てる選択肢がある。専有ノードであれば他者の影響を受けず、プロキシ層で simulateTransaction の同時実行数や compute unit 上限を制御する設定も自由にできる。

ノード運営者が取るべき対策

ノード運営者が取るべき対策

この問題の本質的な解決は、ノード運営者または RPC プロバイダー側の実装にある。運営に携わる人や、自前ノードを管理する開発者向けに要点をまとめる。

simulateTransaction 専用のワーカープールを分離する

最も効果的な対策は、simulateTransaction 専用のスレッドプールを別に用意することだ。通常の RPC メソッドと実行リソースを分けることで、シミュレーションがブロックしても残高照会やトランザクション送信には影響しなくなる。

プロキシ層で IP ごとの同時実行数を制限する

単純なリクエスト数ではなく、「同時に実行中のシミュレーション数」を IP ごとに制限する。たとえば「1 IP あたり最大 2 並列まで」とすれば、特定の送信元が全ワーカーを占有する事態を防げる。

compute unit 上限をプロキシで強制的に制限する

リクエストで指定された maxComputeUnits が大きすぎる場合、プロキシ層で上限値を上書きする。標準的なトランザクションであれば 20 万 〜 50 万 units で十分なケースが多い。無制限な値を許さないだけで、平均占有時間は大幅に短縮される。

よくある質問

simulateTransaction が遅いとき、他の RPC エンドポイントに切り替えれば直るのか

はい、多くの場合は改善する。公開エンドポイントは特に混雑しやすいため、専用 RPC プロバイダーを使うか、運営元の異なる別の公開エンドポイントを試すことで、占有問題の影響を受けにくくなる。

ウォレットでトランザクションを承認しようとすると毎回タイムアウトする

ウォレットが裏側で simulateTransaction を実行している可能性が高い。Phantom や Solflare などのウォレットでは、設定から RPC エンドポイントを変更できるものもある。カスタム RPC に専用プロバイダーの URL を指定することで解決しやすい。

シミュレーションをそもそもスキップできないのか

ウォレットや dApp によっては、シミュレーションを省略して直接トランザクションを送信するモードがある。ただしシミュレーションなしではトランザクションの失敗を事前に検知できず、手数料が無駄になるリスクが上がる。信頼できる操作であれば有効だが、慎重に使う必要がある。

自前ノードを立てる場合の推奨スペックは

Solana の RPC ノードはメモリと高速な NVMe SSD が重要になる。2026 年時点では最低 256GB RAM、1TB 以上の NVMe ストレージ、高速な CPU(32 コア以上推奨)が目安だ。シミュレーション用のワーカープールを増やすなら CPU コア数がものを言う。最新の公式ドキュメントでハードウェア要件を必ず確認してほしい。

この記事のポイント

  • simulateTransaction の遅延原因は、リクエスト数ではなくワーカースレッドの占有時間にある
  • 少数の重いシミュレーションが全 RPC 処理を巻き添えにする構造的問題
  • 専用 RPC プロバイダーの利用が最も手軽で効果的な対策
  • ノード運営者は専用プールの分離や compute unit 制限で根本対処が可能
  • タイムアウト設定と maxComputeUnits の見直しは今すぐできる自衛策
共有:

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)