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¶
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:
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:
Docs¶
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:
or bind to an interface the client can reach:
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 withdetailed-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.