Performance Overview¶
Docs-site note (2026-06-25, refreshed 2026-07-11): Part of the planned Vexor documentation site (Anza-style). Vexor is testnet-only, version 0.9.x pre-production. This page describes Vexor's performance philosophy and the headline facts measured on the live testnet validator. Every claim below traces to source code or a live cluster measurement; where a number is not established it is described qualitatively rather than invented.
Philosophy¶
Vexor is a from-scratch, 100% Zig Solana validator. Its performance posture is shaped by one hard constraint and one design opportunity:
- The hard constraint — byte-faithfulness. A validator's consensus path is unforgiving: a single wrong byte in a bank hash, lt-hash leaf, vote-state record, or sysvar is a fork divergence, not a slow path. So every optimization on or near the consensus path must be bank-hash-neutral — validated byte-for-byte against the canonical Agave reference implementation (currently anchored to the newest testnet release, v4.2.0-beta.0, with Firedancer and Sig used as engineering references) — or it does not ship armed. Speed is never bought with correctness.
- The opportunity — total control of layout and scheduling. Because the whole consensus client is one Zig
codebase with no Rust FFI on any consensus path — and, since the pure-Zig crypto rewrite (
-Dpure_zig, the canonical production backend), no Firedancer code linked at runtime either, with ed25519 / BLAKE3 / BN254/alt_bn128 / Poseidon all running through Vexor's ownsrc/vex_crypto/— Vexor controls its own memory layout, thread topology, and I/O model end-to-end. That is what makes the techniques below possible.
Three principles fall out of this.
Pinned tiles, not a thread soup¶
Vexor runs as a set of pinned tiles — dedicated threads, each with a declared home core, Firedancer-style — so
latency-critical work never floats or gets preempted by background load. Replay, PoH verification, sigverify
workers, the vote/tx-send path, gossip, and repair each own specific cores; cold/background work (the VexLedger
persist tile, build relief) is fenced onto a separate Core-Complex (CCX) so it cannot evict the hot working set.
The layout is declared in one place (src/vex_topo.zig) and verified at deploy time against /proc — Vexor
proves the live thread→core map and flags any floater on a consensus core. No mainstream validator self-verifies
its pinning like this. See Tuning and the hardware reference for the live
table.
Zero-copy on the hot paths¶
The two firehoses a validator must keep up with — shred ingest from the network and shred serving to repair — are handled without per-packet copies where it counts:
- Ingest runs over an AF_XDP zero-copy datapath: shreds land from the NIC directly into userspace ring buffers, bypassing the kernel network stack's per-packet copy. (Proven live; see Enhancements.)
- Shred serving reads straight out of the VexLedger append-segment files — a lookup returns a slice into the mmap'd segment, so repair/replay get a zero-copy view of the shred bytes.
Byte-faithful without sacrificing speed¶
The consensus-path SIMD wins are precisely the ones that are provably output-identical:
- BLAKE3 AVX-512 for the accounts lt-hash — the one consensus-path AVX-512 kernel, boot KAT-gated. Runs
through Vexor's own pure-Zig BLAKE3 (
-Dpure_zig, canonical); an alternate build option still exists to link Firedancer's ballet BLAKE3 instead. @Vectorauto-vectorization onznver4: the lt-hash add/sub folds compile tovpaddw/vpsubw, and the accounts-index probe uses a 16-lane@Vector(16, u8)compare. These produce identical results to the scalar path — they are just faster ways to compute the same bytes.
The build is compiled with -Dcpu=znver4, so the binary uses the full Zen-4 ISA (AVX-512, SHA-NI, VAES,
VPCLMULQDQ) that the reference EPYC 9374F advertises.
Rewriting a hot path from scratch when a generic implementation becomes the ceiling¶
Vote instructions are the dominant transaction type on testnet by volume (roughly 98% of all signatures in a typical window), so their execution cost is nearly all of the per-slot SVM-native execution time. Vexor's original vote-instruction path was built on a general-purpose, reference-derived implementation with a generic serialization round-trip and heap allocation on the hot path — correct, but not shaped for this specific, extremely repetitive workload. The vote-program rewrite is a Vexor-authored, clean-room implementation derived from Agave 4.2 semantics, shaped after Firedancer's flat-buffer approach: zero-allocation, fixed-offset, stack-decoded. A Sig-derived component served as the differential test oracle during development — every instruction ran through both paths and was compared byte-for-byte before the rewrite was trusted to run alone — and has been fully removed from the tree (Stage 8, 2026-07-12) now that the rewrite is the sole, unconditional live executor. This is the same philosophy as the interpreter and the blockstore below: match the canonical behavior first, prove it byte-for-byte, then earn the speed.
The interpreter is Firedancer parity — not a gap¶
Vexor executes sBPF programs with its own clean-room Zig interpreter (src/vex_bpf2/interpreter.zig), byte-
and bank-exact versus the canonical Agave reference (v4.2.0-beta.0). This is the correct comparison point: a
JIT is an Agave-only feature.
Firedancer also interprets sBPF — so "no JIT" is Firedancer parity, not a Vexor deficiency. Calling it a gap
would be measuring Vexor against the wrong baseline. A JIT is a profiling-gated future option, not a correctness
or parity requirement.
Headline measured facts¶
These are the facts established on the live testnet validator (single-socket AMD EPYC 9374F, Zen 4, 503 GiB RAM, Mellanox ConnectX-6 Dx, Gen5 NVMe — see Hardware). Numbers are what was measured; no synthetic benchmarks are claimed.
| Fact | Detail |
|---|---|
| Voting CURRENT, bank-exact | The node votes in-cluster, stays caught up to the tip, and its bank hash matches the cluster every slot under the full performance configuration (parallel exec + FEC-dedup + AF_XDP composing live). |
| ~98.7% of max vote credits | Measured against the theoretical 16-credits-per-slot ceiling — on par with the Agave reference node Vexor operates alongside. See Accomplished. |
| Block production ~97%+ leader slots | Sustained across a full epoch, confirmed via public RPC and independent skip-rate monitoring — currently empty blocks; transaction-bearing production exists behind a gate and is not yet enabled. |
| AF_XDP zero-copy ingest | Kernel-bypass RX is live on the Mellanox ConnectX-6 Dx — shreds arrive into userspace rings with no per-packet kernel copy. |
| Low write-amp ledger (throughput TBD) | VexLedger writes shreds with low write amplification (write-once, no compaction) versus an LSM's multi-× churn; a specific throughput/write-amp figure is not yet published here — see Tuning for live telemetry. |
| Persist off the consensus path (latency TBD) | The VexLedger persist tile runs on a dedicated cold core; per-slot persist (serialize meta + append + fsync) never stalls replay or voting. Exact per-window latency is reported live as persist_us(avg/max) — see Tuning. |
| Accounts mmap'd, not heap-copied (count/timing TBD) | The parallel snapshot loader mmaps the full account set in a multi-threaded boot burst rather than copying it into the heap; exact account count and boot-burst duration are not yet published here. |
| Vote-instruction execution 4.7× faster, live | The Vexor-authored vote-program rewrite executes a vote instruction in ~1,898 ns versus ~8,926 ns for the path it replaced, with byte-identical output verified over 990,000+ live vote instructions. It is now the sole, unconditional live executor on testnet; the Sig-derived path that served as its test oracle during development has been fully removed from the tree (Stage 8, 2026-07-12). See Enhancements. |
A note on honesty: as of the Stage-A bake migration, most of the performance features in this section are baked on by default at boot —
bakeProdEnvDefaults()sets proven-safe values for feature envs includingVEX_PARALLEL_EXECandVEXOR_ED25519_FEC_DEDUPonly if the operator hasn't already set them (an explicit=0still disarms them), and they are bank-hash-neutral either way. AF_XDP (VEX_ENABLE_AFXDP) is the one feature here that still requires an explicit operator flag. The Enhancements page states the live-vs-gated status of each one plainly. Nothing here is a projection — if a capability is gated, it says so.
Where to go next¶
- Performance Enhancements — an itemized tour of every shipped performance feature, what it does, why it helps, and whether it is live or gated.
- Tuning — the operator-tunable knobs (env vars), safe defaults, and the telemetry to watch.
- VexLedger — the append-segment blockstore and its ~1× write-amp story.
- Hardware — the reference box and the tile→core map.