$ k6 run bench/workload.js

How fast is a verified web server?

Rust (h5i-app), Go, TypeScript and Python serving the same APIs and PostgreSQL data. Tested with k6 at 1–256 concurrent clients after API conformance checks.

Overview

Requests/s at 16 clients. Darker shading means faster within a row. – = unmeasured.

django-cart execution-strategy experiments · SQL, request batching and line scaling

Supplemental measurements compare execution strategies. Their original implementation names and measurement conditions are preserved.

GPU policies

Conduit · 2026-10-18. The same server with CPU or GPU policy decisions.

CUDA handles eight authorization and state decisions. HTTP, SQL and serialization use the same code. The CPU kernel has Lean proofs; GPU behavior is tested against CPU results. List, slug and login are controls that do not use GPU decisions.

End-to-end HTTP requests per second and p99 latency, means of three repetitions. GPU / CPU is the throughput ratio.
ScenarioClientsCPU req/sGPU req/sGPU / CPUCPU p99 msGPU p99 ms
list183.3782.830.99×32.6932.65
list16766.32769.671.00×78.7878.82
slug11,110.161,118.361.01×0.961.00
slug1613,560.1014,174.031.05×8.898.55
feed1187.76179.550.96×5.806.10
feed162,194.922,201.721.00×14.3013.99
login13.853.831.00×260.47261.96
login1615.4515.411.00×1,113.431,104.02
create1196.21190.830.97×5.645.78
create16216.31209.850.97×363.18367.29
favorite1504.53439.160.87×2.633.15
favorite164,457.184,725.081.06×19.1817.90
mixed1121.54123.871.02×35.1333.75
mixed161,001.07982.930.98×68.7071.16

No consistent GPU speedup. Mixed throughput is 0.98× CPU at 16 clients; GPU host RSS is 93–98 MiB versus 7–11 MiB. The 1.06× favorite result is within observed variation. CPU remains the default.

Run conditions
  • 100 users, 10,000 articles, 10,000 comments, 1,000 follows, 5,000 favorites. Three repetitions, fresh database/server, 10 s warmup, 30 s measurement; startup excluded.
  • Dual EPYC 7502, two RTX 3090s. Two CPU/GPU pairs split the scenarios; each variant has 4 server, 4 PostgreSQL and 4 client CPUs. Shared host; clocks and NUMA placement vary.
  • 4,467,960 measured requests; zero failures. GPU execution was logged with no runtime CPU fallback. Paired runs cover 1 and 16 clients; cost and power were not measured.

Report · Summary CSV · Per-point CSV

GPU cart pricing

django-cart 3.1.1 · 2026-10-19. Recalculate already-loaded cart snapshots.

Compare Rust, Go, Node.js and CUDA using identical cart snapshots. Select lines per cart to see how batch size changes the result. Milliseconds per complete batch, lower is faster; median of three repetition means. Hover over a timing for its measured range.

GPU resident reuses unchanged input; upload each transfers all snapshots every call. Both download all totals. A CPU could cache unchanged totals too; useful residency needs changing prices or discount scenarios, including synchronization costs. See candidate workloads and evaluation requirements. This is an offline calculation microbenchmark. For HTTP request coalescing and SQL query batching, see django-cart totals and the 32–2,048 lines/cart comparison above. Session handling, database aggregation and checkout transactions are excluded. This does not establish a speedup over a Django deployment.

Run conditions and correctness
  • EPYC 7502, CPUs 64–79, RTX 3090 device 0, CUDA 12.6. Eight warmup passes; three repetitions, each averaging 100 iterations below 4,096 carts and 10 otherwise; shared host and uncontrolled clocks/NUMA placement.
  • GPU snapshots are transposed on upload for contiguous reads; upload-each timing includes that conversion. The same integer pricing source runs on CPU and CUDA using h5i's NVVM launch shell. CPU 16 uses persistent Rayon workers. GPU resident timing includes launch, synchronization, result allocation, download and error validation.
  • 4,146 cases agree with the pinned upstream's Decimal methods; 49 exercise its ORM aggregate. Rust, Go, Node.js and CUDA agree with this corpus. CPU/GPU checks also cover malformed snapshots and batch boundaries. This pricing kernel has no Lean proof.
  • None, percentage and fixed discounts, final half-up rounding, default zero tax/shipping. Fixed-width snapshots reserve 32 lines; no mutations or live cache invalidation are measured.

Contract and reproduction · All batch sizes · Upstream source

Resident cart updates across languages

Go, JavaScript, Python, NumPy, Rust and GPU: the same changing input and every total returned.

Run conditions and correctness

Every path retains rows, subtotals and totals between batches. Canonical commands contain explicit u64 query IDs and four u64 fields per replacement. Timings include applying updates, pricing, worker dispatch/join and a complete freshly owned output. GPU paths also include encoding where applicable, upload, synchronization and full download. All returned values are checked exactly outside timing. No SQL/HTTP is included.

One or four persistent computation workers; Python 4 uses fork processes, JavaScript 4 uses worker threads, Go 4 uses goroutines, Rust 4 uses Rayon. NumPy is a separate native vectorized implementation with native thread counts fixed to one. All modes share the same four-core allocation (CPUs 64–67), with GC enabled. CPU timings are collected without concurrent benchmark processes. If GPU references from the prior run are shown, their status is explicit above and their ratios are not contemporary speedups. JavaScript uses exact Float64 integer subtotals and quotient/remainder discount rounding. CPython loops use Python integers with u64 retained storage; NumPy is used for untimed input validation in every Python mode.

Initial placement, loading, worker creation and validation are excluded. Python imports initial subtotal caches from fixtures, computes initial totals itself, and independently rescans subtotals for every upstream gate; other languages construct their initial caches. Initialization timings are not comparable cache-construction costs. Three repetitions, eight changing warmups and 50 changing timed rounds; RTX 3090 device 0. Shared host; clocks, NUMA and cache placement are uncontrolled. This is a resident calculation/update benchmark, not a Django deployment speedup.

Findings and method · All timings

Cart update and GPU tuning experiments · 2026-10-19–20

Resident update sweeps, transfer diagnostics and compact-buffer comparisons. Calculation timings exclude HTTP and SQL.

Resident carts with updates

CPU and GPU retain the same 4,096-cart population. Apply line replacements, then query current totals.

Microseconds per complete update-and-query batch, lower is faster. GPU includes command upload, mutation/query kernels, synchronization and full result download. CPU and GPU delta maintain subtotals and cached totals; this baseline matters because simple sums do not require full rescans. This is a calculation experiment: database commits, CDC, HTTP and cross-process coherence are excluded.

These initial results use a single-thread CPU delta baseline. See larger cart update batches for grouped single/four-thread CPU delta comparisons.

Run conditions and correctness

Three repetitions × 100 changing rounds after eight warmups. Every warmup and timed output is checked against a separate full-rescan state machine; the very next query must observe replacements. CPU delta is single-threaded; the four-worker CPU path rescans all lines. Parallel CPU delta is not part of this initial run. One/four CPU workers share CPUs 64–67; RTX 3090 device 0. Variant order rotates/reverses; clocks, NUMA, host activity and caches are uncontrolled. Initial placement is separate and includes subtotal initialization for both delta paths. p50/p99 are averaged iteration percentiles, not pooled HTTP percentiles.

Method and limits · All shapes and update rates

Larger cart update batches

4,096–65,536 resident carts, including single/four-thread incremental CPU baselines.

Every cart is queried after changing 1, 16 or 64 of its lines. CPU and GPU retain the same data and cached subtotals. The comparison uses the fastest measured implementation on each side; above 1 favors GPU. GPU timing includes fresh command upload, kernels, synchronization and complete result download.

Measured update transfer, kernel and result phases for four selected conditions.

Run conditions and correctness

Seven implementations × 18 shapes × three repetitions; 50 changing measured rounds after eight warmups. Every output is checked exactly against an independent full-rescan state machine. Grouped CPU delta processes all changes for a cart together, with either one thread or four persistent Rayon workers. CPUs 64–67, RTX 3090 device 0; shared host, uncontrolled clocks/NUMA/cache. Initial placement is separate. Iteration percentiles are averaged across repetitions; with 50 rounds p99 is the maximum round. These are Rust calculation measurements, excluding HTTP, database commits, CDC delivery and durable cache coherence.

Method and findings · All shapes

Cart update GPU phases

Separate changing-trace replay of the 1.79× condition and three larger update batches.

Compact input and pinned-buffer comparison, including packing costs.

Run conditions and correctness

The one-update delta host replay and small-shape delta event replay contain large upload outliers; all rounds are retained. Host columns are disjoint wall-time intervals. Upload/download include pageable staging and driver overhead; they are not isolated PCIe times. Sync includes remaining kernel execution and waiting overhead. Device event intervals come from a separate replay, overlap enqueue/sync, and must not be added to the host columns. Delta fuses update and total gathering in one kernel. All modes replay the same 58 changing rounds from reset state; three repetitions, eight warmups. Initialization is excluded. Shared host, uncontrolled clocks/NUMA/cache.

Findings and method · All phase timings

Compact cart updates and pinned buffers

32-byte versus 8-byte replacements, with pageable or reusable page-locked host staging.

Run conditions and correctness

All paths consume the same canonical commands and return a fresh owned vector of every queried total. Encoding and staging copies are timed. A compact replacement packs slot (11 bits), price (27) and quantity (10); cart ID comes from the validated round-robin query order. Query IDs remain explicit. This format requires that routing contract. Compact encoders run on one or four workers; encode4 uses the same persistent Rayon pool and four-core budget as CPU4. Pinned paths copy/encode into reusable locked input, queue upload/kernels/full download in one stream, wait, then copy locked output into an owned vector. There is no overlap across batches. Initialization is separate.

Plain runs drive comparisons. Event runs are separate diagnostics: upload, kernels and download use the same stream. Pageable upload intervals include possible host submission gaps; they do not isolate DMA. Event readout is included in the diagnostic total. Three repetitions, 50 changing rounds after eight warmups; CPUs 64–67 and RTX 3090 device 0. Shared host, uncontrolled clocks/NUMA/cache. Controls retain the original host calls and kernel source, compiled into a separate PTX. HTTP, database commits and CDC are excluded.

Findings and method · All timings

Linkding tuning experiments · 2026-10-18

Separate before/after runs; these results are not included in the overview.

Linkding search initialization

Post-seed ANALYZE · 2026-10-18.

Requests/s, mean of three repetitions. Separate from the overview runs.
ScenarioClientsBeforeAfterAfter / before
get1480.12462.900.96×
get6411407.4411503.831.01×
list131.7221.600.68×
list64136.91120.640.88×
search10.971.871.93×
search644.137.541.83×

Search improves 1.83× at 64 clients; list throughput falls to 0.88×. Instrumented runs: 5 s warmup, 15 s measurement, three repetitions. Search reads 287,002 physical rows per request.

Report · Summary CSV

Linkding retrieval, creation and search

Combined bookmark/tag retrieval and scalar SQL · 2026-10-18.

Requests/s, mean of three repetitions. Separate from the overview runs.
RouteClientsBeforeAfterRatioReferenceReference req/s
Optimized get1460.12694.761.51×h5i475.71
Optimized get644353.986573.411.51×h5i8582.49
Engine create148.54174.663.60×Go152.26
Engine create6429.88224.817.52×Go3525.29
Engine search11.862.361.27×Go4.73
Engine search646.6810.241.53×Go19.21

Get improves 1.51×. Engine creation and search improve, but Go stays faster at 64 clients. No timing probes; three repetitions with CPU/database slot rotation. Read SQL is differential-tested; the kernel and its Lean proofs are unchanged.

Report · Summary CSVs

Single-bookmark retrieval

Reuse the authorized bookmark row · 2026-10-18.

Requests/s, mean of three repetitions. Separate from the overview runs.
ClientsBeforeAfterRatioGo
1331.60399.481.20×402.78
642866.833676.611.28×6450.85

Get improves 1.20–1.28×. Go was measured concurrently on a shared host with slot rotation. Three repetitions, 5 s warmup and 15 s measurement; zero failures. The earlier sequential run regressed at 64 clients; see the report.

Report · Summary CSV

Read SQL modes

Membership versus scalar subqueries · 2026-10-18.

Requests/s, mean of three repetitions. Separate from the overview runs.
ClientsMembershipScalar when uniqueRatio
131.2047.861.53×
64154.11259.121.68×

Scalar mode improves list throughput 1.53–1.68× at fixed offset 100. Timing probes enabled; three repetitions. Both modes return 20 results and an exact total of 95,000. The earlier rotating-offset regression remains unresolved; IN remains the default.

Report · Summary CSV

Unique-membership SQL

Scalar subqueries for primary-key membership · 2026-10-18.

Requests/s, mean of three repetitions. Separate from the overview runs.
ScenarioClientsBeforeAfterAfter / before
get1480.17490.781.02×
get6411443.3411180.280.98×
list121.8122.231.02×
list64120.26107.660.90×
search11.872.401.28×
search647.7011.811.53×

Search improves 1.28–1.53×; list throughput falls to 0.90× at 64 clients. Instrumented runs: 5 s warmup, 15 s measurement, three repetitions. Read SQL is differential-tested; application decisions and read/count plans are unchanged.

Report · Summary CSV

Method

Overview runs: fresh seed, 10 s warmup, 30 s measurement, mean of three repetitions. Targeted experiments list their own conditions.