argotdocs

Performance

Where the time goes, the machine-wide embedding cache, multi-core calibration — and the one rule behind all of it, results that never change with speed.

argot is a single static binary that does everything in-process — fit, check, audit, the semantic index, the architecture graph, the test-integrity gates. Its performance design follows one rule and three mechanisms.

The rule: speed never changes a result. Same repo, same window, same model → the same findings, byte for byte, whether the caches were cold or warm and whatever the core count. Parallelism and caching are allowed to change when you get the answer, never what it is. Embedding vectors are canonicalized to f16 at the source, so a cached vector and a freshly computed one are bit-identical by construction; parallel work is per-item only, and aggregation stays sequential and ordered.

Where the time goes

The two mechanisms

1. A machine-wide, content-addressed embedding cache

Every embedding is stored under ~/.cache/argot/embeddings/, keyed by the embedding model’s identity and the content of the function. A function that hasn’t changed is never embedded twice — not across commits, not across clones or worktrees of the same repo, not across repos that share vendored code. A fresh clone of a repo your machine has already seen rebuilds its semantic index mostly from cache. Bumping the embedding model invalidates the cache naturally (it’s part of the key); stale entries can be deleted at any time — the cache is a pure accelerator, never a source of truth.

The cache is only safe because embeddings are canonicalized to f16 at the source: the encoder’s f32 output jitters in its low bits run-to-run (Metal reduction order), but rounds to the same f16 that the index and the cache store — so a cache-served vector and a freshly computed one are bit-identical, and a cache hit can never change a finding.

2. Multi-core calibration and scoring

Calibration probes, semantic candidate scoring at check time, and the integrity replay are all per-item-independent computations — so they run on every core. The order-sensitive part (threshold aggregation, evidence assembly) stays sequential, which is what keeps the output independent of the core count. (Sequence-level batching of the embedder was tried and dropped — it perturbed the low bits enough to flip a cosine tie and change a finding; the invariant wins over the lever.)

Sharing the machine: set ARGOT_THREADS=<n> to cap every worker pool in the binary — the calibration/scoring phases and the embedder’s compute threads — so a fit in a pre-commit hook doesn’t saturate the machine while you build. It only changes wall-clock, never a finding. There is no memory knob: peak RSS is dominated by the embedding model plus the per-thread working set, so lowering ARGOT_THREADS also lowers peak memory.

Measured numbers

No released, canonical timing dataset is currently approved for public performance claims. Hardware, repository shape, history depth, changed range, and whether the embedding cache is warm materially affect fit, check, and audit time. Use ARGOT_TIMING=1 on the repository and command you care about, and retain the command, revision, hardware, cache state, and range with any comparison. Benchmark methodology and result provenance belong in the research evidence.

Diagnostics

Set ARGOT_TIMING=1 to print a per-phase wall-clock split to stderr on any command (train, calibrate, semantic index — embed vs reuse —, arch graph, integrity replay, check phases, attribution). If argot ever feels slow, that split is the first thing to attach to an issue.

CI

The GitHub Action reads the committed fit snapshot from the base commit and never fits on an ephemeral runner. The machine-wide embedding cache remains a local accelerator for the maintainer who refreshes that snapshot.