Skip to content

Development

Build modes

Command Profile Detailed metrics
uv sync --extra dev dev (fast incremental) off
just install dev off
just develop dev on
just install-telemetry release on
just build-whl release off

detailed-metrics adds three hdrhistograms (memcpy, drain_round, queue_dwell) and CAS counters. Off by default; turn on for perf investigation. See Reading metrics for what they give you.

Tests

cargo test                       # Rust unit + integration tests
uv run pytest python/tests/ -v   # Python tests

Rust tests live in tests/, one file per module — including tests/host_pinning.rs. Python tests live in python/tests/.

Working on host-memory pinning

See Host-memory pinning for how the module is laid out, and the guide for what it does for a user.

Most of tests/host_pinning.rs needs no GPU: the resolution ladder is pure, and registration and rollback run against injected stubs.

To exercise the CUDA-runtime resolution ladder locally, install a runtime wheel into the checkout's venv:

uv pip install nvidia-cuda-runtime

Without it only rung 1 (already-mapped libraries) can hit, and on a machine with no system CUDA install nothing resolves at all. The wheel is not a dev extra: CI is CPU-only and should not download a CUDA runtime.

cargo test has no Python interpreter to ask for the wheel's location, so the Rust tests look under .venv/lib/python*/site-packages/nvidia in the checkout.

Benchmarks

just bench               # ray-based, requires uv sync --extra distributed
just bench-rs            # Rust micro-benchmarks, ~1 minute
just bench-rs insert_batch   # only benches whose name matches the regex

Benchmark results land in benches/.

benches/micro.rs drives the Rust hot path directly, with no network or drainer runtime. Each group runs over four pytree shapes: atari, small, medium and large. large is the pytree bench_distributed.py sends, and it peaks at about 800 MB resident.

Group Measures
memcpy The raw ring writes alone: the floor under insert_batch.
insert_batch The drainer's insert path for one batch, plus the sample that releases it.
reservation insert_batch with 1-byte samples, in chunks of 1, 16 or 256: the per-reservation cost.
fifo_sampler FifoSampler::commit_batch and select on their own.
sample The consumer's Store::sample, which scales with the number of arrays.
drain_round A full drainer round over 32 connections.

To compare a change against main, save a baseline on main, then compare against it on your branch:

just bench-rs --save-baseline main   # on main
just bench-rs --baseline main        # on your branch

Docs

just docs-serve   # live-reload on http://127.0.0.1:8000/echo/
just docs         # static site to docs/site/

Note the /echo/ path prefix — mkdocs serve honours site_url, so http://127.0.0.1:8000/ alone 404s. The address it prints on startup is correct.

Working on a remote box, docs-serve binds to loopback only and is invisible from your laptop. Either forward the port from the client side, which needs no change here:

ssh -L 8000:localhost:8000 you@remote-box    # then browse http://localhost:8000/echo/

or bind to an interface the client can reach:

just docs-serve-on                  # 0.0.0.0:8000 — all interfaces
just docs-serve-on 10.0.0.5:8000    # just this one

Prefer the tunnel, or a specific private interface, over 0.0.0.0 on an untrusted network: mkdocs serve is a development server with no authentication.

The docs are built and deployed by .github/workflows/docs.yml on every push to main.

The mkdocstrings plugin pulls signatures and docstrings live from python/echo/. Edit a docstring there and mkdocs serve will hot-reload the corresponding API page.

Just recipes

just with no args lists every recipe. The commonly-used ones:

  • just install: editable install in dev profile.
  • just develop: dev build with detailed-metrics, for perf work.
  • just build-whl: manylinux release wheel.
  • just bench: distributed benchmark.
  • just bench-rs: Rust micro-benchmarks.
  • just docs-serve: live-reload docs.
  • just docs: build static docs.