Crystal benchmarking
A set of skills to help with Crystal development
npx -y skills add dsisnero/crystal_forge --skill crystal-benchmarkingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build or repair Crystal benchmark harnesses and use them to measure throughput, latency, concurrency scaling, and hotspot location with real numbers. Use whenever the user asks for benchmarks, speedup data, throughput comparisons, worker-count comparisons, concurrency validation, hotspot analysis, or says not to guess about performance.
SKILL.md
5.0 KB, 989 tokens by cl100k_base, as published. Nobody here has run it
Crystal Benchmarking
Use this skill when the question is not "how should this be structured?" but "what does the runtime actually do?".
This skill is specifically for:
- proving whether a concurrency change improves throughput
- comparing sequential vs bounded-concurrent vs async return paths
- identifying the real hotspot before changing more code
- measuring worker-count scaling such as
x1,xN, orsequentialbaselines - separating return latency from deferred/background work latency
If the task is general optimization, also read crystal-performance.
If the task is about concurrency architecture or channel/fiber correctness,
also read crystal-concurrency.
What this skill is for
Benchmarking is a separate discipline from both optimization and concurrency design. A code path can be:
- concurrent but slower
- asynchronous at the API boundary but still throughput-neutral
- structurally elegant but not a hotspot
- flat in microbenchmarks and still valuable for tail latency
Do not infer wins from code structure alone.
Core rules
- Measure the real path, not a toy helper, unless the helper itself is the question.
- Always compare against a named baseline.
- Run at least 3 times and discard the cold run unless the cold path itself matters.
- Distinguish throughput from return latency.
- Distinguish concurrency from parallelism.
- Keep flat or regressed results; they are part of the outcome.
- If a benchmark takes too long to be useful, parameterize it instead of guessing.
Benchmark questions to answer
Every benchmark pass should explicitly answer one or more of:
- Is this code actually a hotspot?
- Does bounded concurrency help at all?
- At what worker count does it flatten or regress?
- Is the win in total throughput, return latency, or both?
- Is the dominant cost file I/O, parsing, extraction, FFI, serialization, or cache persistence?
Standard comparison set
For concurrency-sensitive code, prefer this comparison matrix:
sequentialconcurrent x1concurrent xNasync returnasync flushorbackground completion
Use only the rows that make sense for the path.
Examples:
- file prep:
sequential,x1,xN - discovery/extraction:
sequential baseline,pipeline x1,pipeline xN - async cache write:
return latency,flush latency
Harness design
Parameterize size
Benchmarks should be controllable with environment variables or arguments:
- file count
- payload size
- worker count
- run count
- section selection
This lets you shrink the run to get signal quickly, then scale up the hot path.
Isolate sections
If one section dominates the run, make benchmark sections selectable so you can rerun only:
- file I/O
- search prep
- discovery
- extract graph
- cache flush
Keep fixture generation deterministic
Use generated local fixtures where possible:
- fixed file counts
- fixed method/function counts
- stable names
- no network
Concurrency-specific guidance
File I/O
Do not assume concurrent file reads are a win. On fast local disks they are often flat or slightly worse. Measure before keeping that complexity.
Discovery and extraction
This is often where the real cost lives: parser setup, tree-sitter parse, query execution, AST walking, symbol extraction.
If file I/O is flat but discovery is slow, stop micro-optimizing readers and benchmark parser/extractor stages directly.
Async persistence
For cache or snapshot writes, measure two numbers:
- how fast the caller returns
- how long flush/background completion takes
If return latency improves materially and flush stays bounded, async persistence may still be worthwhile even when total work is unchanged.
CPU-bound work
If bounded fibers show only small gains on a CPU-heavy path, benchmark whether
the bottleneck is actually parallelizable before reaching for
ExecutionContext::Parallel.
Output format
Always report:
- exact benchmark command
- fixture size and worker count
- baseline and comparison rows
- average warm time and cold time
- what the numbers imply
- next action based on the data
Use direct conclusions such as:
- "file I/O is not the hotspot"
- "search prep is flat; do not optimize this next"
- "discovery dominates runtime and current concurrency only buys ~12%"
- "async cache improves return latency but not total work"
When to stop
Stop benchmarking and switch back to implementation when:
- one hotspot clearly dominates
- a proposed optimization target has measurable headroom
- a concurrency feature is shown to be flat or regressive
At that point, the benchmark result becomes the gate for the next code change.
Gives 0 of the 12 instructions most performance cost skills give in 989 tokens
Counted across 803 of the 1,058 authors here whose files we hold, read 2026-08-06
- keep skill files under 500 linesin 82 of 803, across 17 files
- use imperative form in instructionsin 81 of 803, across 10 files
- draft assertions while test runs are in progressin 75 of 803, across 9 files
- create two to three realistic test promptsin 74 of 803, across 8 files
- write skill descriptions to be pushyin 72 of 803, across 7 files
- save test cases to evals jsonin 72 of 803, across 6 files
- ask questions about edge cases and input formatsin 71 of 803, across 6 files
- save timing data immediately when runs completein 70 of 803, across 5 files
- include all trigger conditions in the skill descriptionin 69 of 803, across 3 files
- launch all test runs in a single turnin 69 of 803, across 3 files
- capture intent before writing a skillin 67 of 803, across 1 file
- import directly instead of barrel filesin 52 of 803, across 15 files
Said here and by no other author read
- measure the real code path
- discard the cold run
- distinguish throughput from return latency
- keep flat or regressed results
- parameterize benchmark size
- make benchmark sections selectable
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.