julia-performance
Measure Julia performance so that the number means something: allocations, type stability, timings and before/after comparisons, each in a cold process with…
Skill by michakraus
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/michakraus-julia-performance
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: testing, ml, security
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/julia-performance
What's inside
- Skill name
julia-performance- Description
- Measure Julia performance so that the number means something: allocations, type stability, timings and before/after comparisons, each in a cold process with the traps of this tree. Load it first, before reading code, for any question about the speed, memory or inference of Julia code, even a one-line question with no code attached. Typical words: allocates, allocation count, @allocated, @btime, @benchmark, BenchmarkTools, @code_warntype, @inferred, JET, runtime dispatch, inference, type instability, slower, faster, speed-up, slowdown after a merge or an update, performance regression, compare a branch with main, is the fix worth it, a failing allocation test. For a whole-package quality sweep, use julia-package-audit instead.
- License
- MIT
- Instructions
- 158 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Julia performance measurement
Every rule here exists because it was violated once and produced a confident wrong number.
The failure mode is never a crash — it is a measurement that looks fine and means nothing.
**Contents**
- [Before measuring](#before-measuring)
- [Timing](#timing)
- [Allocations](#allocations)
- [Type stability](#type-stability)
- [A/B the change, not two inputs](#ab-the-change-not-two-inputs)
- [Guarantees hold only where asserted](#guarantees-hold-only-where-asserted)
- [Report](#report)
## Before measuring
**Measure cold, in a fresh process.** A sweep inside one session measures what the previous row
compiled. Start a new `julia` for each configuration you intend to compare. Two variants timed in
one process give the first one the compilation cost. Run each variant twice in its own process, and
label the cold and warm columns. A build-cost figure is the exception and stays valid, because the
docs build runs the later blocks warm.
**Warm up before timing.** The first build or call in a process measures compilation, not the
code. Take a median over repeats, not a single reading.
**Print the resolved versions next to any cross-version measurement.** A probe environment that
silently resolved the *registered* package instead of the working tree has produced a pre-fix
figure reported as post-fix.
**Do not measure while a test suite is running** over any of the same packages. `Pkg.test()`'s
`--check-bounds=yes` on 1.12 and earlier diverges from your `auto`, the shared precompile images
invalidate each other, and you will be timing recompilation. Disjoint packages or matching flags
are fine.
**Pin `BLAS.set_num_threads(1)` inside the script** before you quote a ratio for a change to dense
arithmetic, and state the thread count. Multithreaded BLAS gives a large square product its loss
back by an amount set by idle cores; one script gave 2.1, 3.3 and 756 for one code. Read the cost
class off the expression, and do not fit an exponent: at reachable sizes allocation dominates the
small end and `gemm` the large end.
## Timing
**Give the timed call its own statement.** Julia compiles a whole top-level statement before it
runs it. In `println(@elapsed f(x))` the callee compiles before the timer starts, so the cold
figure comes out warm, repeatably. Write `t = @elapsed SINK[] = f(x)` with `const SINK = Ref{Any}(nothing)`.
**Check every cold figure twice.** Time a second call in the same process, and check that the two
differ by the factor compilation explains. Then compare with an independent run.
**Below ~1 µs per call, one call per sample measures the clock.** `time_ns()` on this Apple Silicon
host advances in 41–42 ns ticks. Fold calls into each sample until it lasts ≥ 20 µs, then divide.
Size the block with `c = ceil(Int, 2e-5 / @elapsed f(x))`, take the median over samples, and run
the script cold three times. At the smallest size the ratio still moves between runs, so publish a
range there, not one figure.
**Time the shape a user writes.** `foreach` over a `Vector` of closures puts every dynamic dispatch
inside the timed region.
## Allocations
**`Pkg.test()` forces `--check-bounds=yes` up to Julia 1.12.** There it inflates timings roughly
4× **and skips every guarded `@allocated` assertion**; from 1.13 it inherits the session's `auto`.
On the `[min, 1]` matrix a bound is therefore enforced on `1` and skipped on `min`, so green CI is
*not* evidence for an allocation bound on the floor. Run with `--check-bounds=auto` when allocations are the point:
```bash
julia --project --check-bounds=auto -e 'using Pkg; Pkg.test(; julia_args=["--check-bounds=auto"])'
```
**`@allocated` equality is not portable.** It drifts tens of bytes per call and ~30 % between
builds; Windows jitters in both directions. Assert a **ceiling or a spread**, never `==`.
**One `@allocated` call can be off by orders of magnitude.** A GC interaction or a buffer resize
lands in it, and the output does not show this. Sweep several sizes and read the trend. Take a
minimum over repeats, and distrust a row that breaks the trend of its neighbours. A warm-up call
removes compilation, not this noise.
**`@allocated` around a constructor measures the constructor**, not the work the caller did to
build its argument. To compare retained storage, use `Base.summarysize`.
**`Profile.Allocs` gives correct counts and wrong sizes.** Use it to find which `file:line`
allocates and how often. Take every byte figure from `@allocated` on a warm call in a cold process.
**Measure the shape a consumer actually holds.** A bare `NamedTuple` benchmark reports the cheap
column and calls it the cost.
## Type stability
`@code_warntype` on the entry point, `@inferred` in tests.
**`@inferred` drops literal arguments** — it cannot test constant propagation. Wrap the call in
a closure if that is what you mean to check.
A `CacheType` that reads a value off the problem rather than constant-folding costs ~5×
allocations. If a type parameter is computed at runtime, inference has already lost.
## A/B the change, not two inputs
To claim a change did or did not affect performance, toggle **that change** with everything else
fixed. Comparing two different inputs, two different Julia versions, or two different
environments answers a different question.
"This is not a performance fix" needs the with/without toggle just as much as "this is".
The new variant is the shipped function, never a copy in the script: a copy goes stale silently
when review edits the method. Write out only the replaced variant, and have it return the same
wrapper type as the method, so the byte columns compare like with like. Reach the old one with `invoke`, or run the same script file in a
worktree at the base commit, and name the commit.
`invoke` works when the fix adds a more specific method. Copy the shadowed method's own signature,
without the function type, from its definition:
```julia
invoke(rand,
Tuple{CPU, Random.AbstractRNG, Type{MT}, Integer, Integer} where {T, MT <: Manifold{T}},
CPU(), Random.default_rng(), SymplecticStiefelManifold{Float64}, 6, 4)
```From michakraus/ResearchHarness, MIT.
More from michakraus/ResearchHarness
- 0.598score
build-part
michakraus
Run the next part of a decomposed task file through the builder-critic loop.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
build-reviewed
michakraus
Build one part of a decomposed task file whose tier cell is reviewed: one part-builder, one blind part-critic, at most one fix round by a new part-builder…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
julia-package-audit
michakraus
Audit the correctness and code quality of a whole Julia package, and return one findings report in a fixed format: type piracy, type instabilities, avoidable…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
julia-release
michakraus
Release and register a Julia package in the General registry.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
math-verify
michakraus
Check one mathematical statement in Julia, analytically, symbolically or numerically, together with a case that should make the check fail, and keep the check…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
plan-parts
michakraus
Plan work as parts that are each one pull request, and write each part's spec so that the builder-critic loop can build it and judge it: the parts table, the…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
julia-surgical-fix
michakraus
Fix a reported problem in a Julia repository so that the diff holds that fix and nothing else, then check it again: the scope rule, the fix and re-verify…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
latex-revision
michakraus
Run a revision pass over a LaTeX manuscript with colour-marked changes.
SkillAFreshness: A★ 2Claude Code +9 - 0.594score
julia-structure
michakraus
Answer a structural question about Julia code with tools that read it as Julia, not with grep: julia-methods.jl, Kaimon's live session and julia-callers.jl…
SkillAFreshness: A★ 2Claude Code +9 - 0.565score
which-model
michakraus
Probe: report which model runs a typed slash command whose frontmatter names the tier small.
SkillAFreshness: A★ 2Claude Code +9
Signals
- Stars
- 2
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 9, 2026 (20 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/michakraus/ResearchHarness
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from michakraus
- 0.598score
build-part
michakraus
Run the next part of a decomposed task file through the builder-critic loop.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
build-reviewed
michakraus
Build one part of a decomposed task file whose tier cell is reviewed: one part-builder, one blind part-critic, at most one fix round by a new part-builder…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
julia-package-audit
michakraus
Audit the correctness and code quality of a whole Julia package, and return one findings report in a fixed format: type piracy, type instabilities, avoidable…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
julia-release
michakraus
Release and register a Julia package in the General registry.
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
math-verify
michakraus
Check one mathematical statement in Julia, analytically, symbolically or numerically, together with a case that should make the check fail, and keep the check…
SkillAFreshness: A★ 2Claude Code +9 - 0.598score
plan-parts
michakraus
Plan work as parts that are each one pull request, and write each part's spec so that the builder-critic loop can build it and judge it: the parts table, the…
SkillAFreshness: A★ 2Claude Code +9
Cite this page
julia-performance skill. Agent Mart. https://agentmart.dev/skills/michakraus-julia-performance (last updated 2026-10-24)