The CLI is one consumer of these modules; nothing here needs it. Everything below
is importable from a plain pip install armsmith, has no network access, and no
Arm hardware requirement unless stated.
pip install armsmithThe part most worth stealing. Median-of-N with a scaled-MAD noise band, and a
refuse-to-claim rule: a delta inside the band is no_change, never a win.
from armsmith.benchstats import compare, summarize, plan_interleaved| field | meaning |
|---|---|
n |
sample count |
median, p50, p95 |
order statistics |
mad |
median absolute deviation |
smad |
MAD scaled by 1.4826 β a robust Ο estimate |
mean, stddev, min, max |
reported, never used for verdicts |
from armsmith.benchstats import compare, Direction
c = compare([1.00, 1.02, 0.99], [0.60, 0.62, 0.59])
c.verdict # Verdict.IMPROVED
c.delta # -0.40 (median difference)
c.delta_pct # -40.0
c.band # k * smad(baseline) β the noise floor
c.reason # human-readable, quoted verbatim into reportsverdict is IMPROVED, REGRESSED, NO_CHANGE, or INSUFFICIENT_DATA.
NO_CHANGE is returned whenever abs(delta) <= band, regardless of sign β
that single line is the whole honesty thesis.
ABAB scheduling, so machine drift lands on both sides instead of on whichever
ran second. Each Slot has .variant and .warmup.
from armsmith.gate import GateConfig, MeasurementSet, run_gate
outcome = run_gate(baseline_set, [candidate_set], GateConfig(primary_metrics=("wall_s",)))
outcome.results[0].verdict # "keep" | "drop"
outcome.results[0].reasons # why β always populated, including for dropsA candidate is kept only if at least one primary metric improved outside its
noise band and the output hash matches. MeasurementSet carries
variant, instrument, metrics (name β samples), output_sha256,
rule_id, and a required boolean synthetic β loaders raise on records that
omit it, so unlabelled measurement data cannot enter a report.
from armsmith.report import build_report, sign_report, verify_report, schema_pathbuild_report(*, mode, scenario, repo, host, findings, outcome, ..., synthetic=None)βmodeis transport ("live"/"replay"),syntheticis provenance. They are separate axes: a bundle fromarmsmith recordis replayed but real.sign_report(report, key_dir=None)β ed25519 over canonical JSON.verify_report(report)β content hash, signature, JSON Schema, and a full recompute of every claimed statistic from the embedded raw samples.schema_path()β the packagedreport.schema.json, also served at its$id: https://armsmith.edycu.dev/schema/report.schema.json
from armsmith.witness import count_witness, witness_delta
w = count_witness(objdump_text) # any objdump output, any host
w.dotprod, w.int8_matmul, w.total, w.countsCounts SDOT/UDOT/SMMLA/USMMLA in disassembly. Pure text analysis β it
needs no Arm hardware and no binary, only the objdump text.
from armsmith.rules import load_pack, run_rule, run_all
specs = load_pack() # {"R1": RuleSpec, ...}
finding = run_rule(specs["R4"], repo_path, probe=None)
finding.status # FindingStatus.MATCHED | CLEAN | SKIPPED
finding.evidence # every match, with file:line
finding.fix.kind # "code_suggestion" | "advisory" | "ci_patch" | ...RuleSpec carries title, kind, requires (probe kinds), summary,
fix_generator, expected_gain_range (an estimate, never a result),
citation_url, learning_path, and optional before/after snippets.
Pass probe=None to run static rules only β that is exactly what
armsmith scan does, and it needs no bundle.
from armsmith.benchcmd import run_command_bench
res = run_command_bench("./bench_before.sh", "./bench_after.sh", measured_rounds=7)
res.baseline.to_measurement() # feed straight into run_gateRefuses non-aarch64 hosts, refuses non-deterministic workloads, and reports no
ISA witness because there is no binary to disassemble.
Everything above is exercised by the test suite at 100% line coverage. The report
JSON Schema is the most stable contract here β build against that if you only need
the data. Module APIs may change before 2.0; the schema will not without a
schema_version bump.