You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Hardcoded Semaphore(8) in CommittingState serializes large validator committees #1721
CommittingState.handle caps concurrent validator executions with a hardcoded asyncio.Semaphore(8) (backend/consensus/base.py:1925, introduced in #1272).
For large committees this dominates transaction latency: a 47-validator committee runs as ~6 sequential rounds of 8 (sliding window, but with similar per-validator LLM latencies it behaves like waves). This is the likely cause of the observed "47v is ~10× slower" behavior, and becomes increasingly relevant as appeals push committees to 23+.
Why the cap exists (and why 8 is arbitrary)
Bounding GenVM concurrency is legitimate:
each validator execution spawns a GenVM subprocess → unbounded concurrency risks OOM
But the value 8 is not derived from anything — not container memory limits, host RAM, or committee size. It's a static default from #1272 with no recorded rationale. Meanwhile the RPC path's equivalent bound is already configurable via GENVM_MAX_CONCURRENT (backend/protocol_rpc/endpoints.py:71, default 8).
Proposal
Make the consensus-path bound configurable — either reuse GENVM_MAX_CONCURRENT or add a dedicated env var (e.g. CONSENSUS_VALIDATOR_CONCURRENCY), defaulting to the current 8 for backward compatibility.
Deployments with adequate memory can then raise it to match committee sizes (23–47+) instead of paying a ~6× serialization penalty.
Activity
feat(consensus): make validator execution concurrency configurable (#…
feat(consensus): make validator execution concurrency configurable
feat(consensus): make validator execution concurrency configurable (#…