Documentation

How it works.

What the benchmark measures, how a run becomes a score, and what keeps the leaderboard honest.

Overview

X Compute measures how fast a machine moves data through GPU memory and how fast it multiplies matrices, from inside a browser. A run takes about 45 seconds, produces one number, the X-Score, and places the machine among identical hardware.

Every figure on this site is one of three kinds and is labelled as such: measured by a run, published by a vendor, or estimated from the two.

Workload

Two storage buffers of 256 MiB each are filled with hashed data before anything is timed, so no page is untouched. Each memory kernel walks a whole buffer once per dispatch, 64 bytes per invocation, and consecutive dispatches alternate between the two buffers. A byte is touched again only after 512 MiB of other traffic, far more than any cache holds.

PhaseWhat runsReported
ReadFour 16-byte loads per invocation, XOR-foldedGB/s
WriteFour 16-byte stores, data varies per elementGB/s
CopyLoad from one buffer, store to the other; both directions countGB/s
Random1M invocations, 16 gathers each, at xorshift addressesGB/s
Compute512 × 512 single-precision matrix productGFLOP/s
SustainThe copy kernel, continuouslyGB/s, retention

Loads stay observable: each fold decides a store that the shader compiler cannot predict, so the reads cannot be optimized away. Browsers without WebGPU run the same phases on one CPU thread over system memory. That is a different path, so those runs are scored but never ranked.

Timing

A sample is one compute pass holding about 40 ms of GPU work. With the timestamp-query feature the pass is timed by the GPU itself; without it, samples grow to about 80 ms and are timed from submit to completion, minus the measured cost of an empty submit. The result records which clock was used.

  • Calibrate. Grow the dispatch count until a pass reaches a quarter of the target, then scale to the target.
  • Warm up. Unrecorded passes for up to 500 ms.
  • Sample. Record passes until the phase budget is spent, at least eight.
  • Reject. Drop samples whose modified z-score is above 3.5.
  • Report. The median of what remains.

The engine runs in a dedicated worker. While a phase measures, the page's own render loop is stopped: after each sample it draws exactly one frame and acknowledges, and only then does the next pass start. Visuals never overlap a measurement.

BudgetReadWriteCopyRandomComputeSustain
full5.0 s5.0 s5.0 s4.0 s5.0 s14.0 s
quick1.4 s1.4 s1.4 s1.1 s1.4 s3.5 s

X-Score

One number on a linear scale. The reference machine scores 1,000; a machine twice as fast on every phase scores 2,000. Each metric is divided by its reference, weighted, and combined as a weighted geometric mean.

score = 1000 · Π (xᵢ ÷ refᵢ) ^ wᵢ

MetricReferenceWeight
Read100 GB/s0.22
Write100 GB/s0.13
Copy100 GB/s0.15
Random20 GB/s0.10
Compute50 GFLOP/s0.22
Sustain100 GB/s0.18

The server recomputes the score from the submitted metrics; the browser's own number is never stored. Score version v1, engine xc-1.

Decode ceiling

Generating one token reads every active weight once, so tokens per second cannot exceed read throughput divided by the bytes of active weights. At 100 GB/s, an 8B model at 4-bit is 4 GB of weights and at most 25 tokens per second. Real runtimes land below the ceiling. The model planner applies this to any hardware.

Device classes

A class is one GPU model: RTX 4070, Apple M4 Pro, Iris Xe. The model comes from the renderer string the browser reports, and the server parses it again itself. A class with a fixed memory configuration carries a published peak: bus width × data rate ÷ 8 for discrete cards, the vendor's figure for Apple silicon and datacenter parts. Laptop and integrated GPUs ship in many configurations, so they have no fixed peak and are ranked against their own runs only.

Validation

Browser numbers cannot be proven honest. They can be made hard to fake by accident and awkward to fake on purpose. Every submission gets exactly one status: verified, unranked or rejected. Only verified runs rank or earn points.

  • A run opens with a ticket signed by the server. It must be at least 25 seconds old when the result arrives, and at most 30 minutes.
  • The ticket's nonce is the run id, and the insert refuses to overwrite. A replayed ticket is refused.
  • The claimed duration cannot exceed the ticket's age.
FlagOutcomeMeaning
engine-mismatchrejectedSent by an engine version this network does not know.
bad-shaperejectedThe result was incomplete.
too-few-samplesrejectedA phase kept fewer than five samples.
non-finiterejectedA phase reported zero or a value that is not a number.
too-shortrejectedThe run finished faster than the phases allow.
ticket-youngrejectedThe result arrived sooner than a run can finish.
ticket-expiredrejectedThe run ticket expired. Tickets last 30 minutes.
duration-mismatchrejectedThe claimed duration is longer than the ticket has existed.
random-over-streamrejectedRandom access came out faster than streaming allows.
copy-over-streamrejectedCopy came out faster than read and write allow.
sustain-over-copyrejectedSustained throughput came out above the copy phase.
over-published-peakrejectedThroughput is above what this hardware's memory bus can carry.
near-published-peakunrankedThroughput is slightly above the published peak for this class.
quick-modeunrankedQuick run. Shorter phases give a preview, not a ranked result.
cpu-engineunrankedMeasured on the CPU because this browser has no WebGPU.
model-hiddenunrankedThis browser hides the GPU model, so the run cannot join a class.
model-unlistedunrankedThe GPU model is not in the spec table yet.
software-rendererunrankedA software renderer did the work, not a GPU.
small-working-setunrankedThe GPU allowed less than 128 MiB of working memory.
unstableunrankedSamples varied by more than 30%. Close other GPU work and run again.
tab-hiddennoteThe tab was hidden for part of the run.
wall-clocknoteTimed with the wall clock; this browser offers no GPU timestamps.
daily-capnoteRanked, but past today's rewarded runs for this operator. No points.
network-capnoteRanked, but past today's rewarded runs for this network. No points.
form-factor-declarednoteLaptop or desktop was declared, not detected.

The Wafer and proof

Every full run becomes one die on the wafer, filled from the centre outward. 256 dies complete a wafer. Brightness follows the score on a log scale.

Each UTC day, verified runs are hashed into one Merkle root. A leaf commits to the run id, timestamp, class, score and operator, all public, so anyone can rebuild a day's tree and check a run against its root. Roots are published on the wafer page today. Writing them on-chain is planned with the first reward season.

Identity and privacy

  • No account and no cookies. Your identity is a random key generated and kept in this browser.
  • A run publishes its scores, the GPU model, and the browser and OS family. Nothing else.
  • IP addresses are not stored. A keyed hash that changes every day counts runs per network, for the daily cap only.
  • No hardware fingerprint is taken or kept.
  • Linking a wallet stores its public address against your operator. You can unlink it at any time.

Architecture

  • Engine. WGSL kernels and robust statistics in a dedicated worker, with a main-thread fallback where workers have no GPU.
  • Visuals. three.js, one shader for the wafer, drawn once per sample during a run and paused off-screen.
  • Server. Next.js route handlers on Vercel. They validate, store and rank; they never measure.
  • Storage. One immutable document per run, plus an index updated with optimistic concurrency.
  • Chain. Robinhood Chain, chain id 4663. Holder tiers are a read of balanceOf on the linked wallet. Nothing is custodied.

API

Public, read-only, JSON. Cached for a few seconds at the edge.

GET/api/statsNetwork totals, the latest runs and the dies of the current wafer
GET/api/leaderboard?window=all|week|dayEvery class with its medians, and the top runs
GET/api/runs/{id}One run in full, with its class percentile
GET/api/proofDaily Merkle roots of verified runs
GET/api/proof?run={id}One run's leaf, sibling path and day root
GET/api/tokenLive market data, once the token exists
POST/api/ticketOpens a run: returns a signed, single-use ticket
POST/api/submitSubmits a result for validation

Reading is one thing. Measuring takes 45 seconds.