criterium

0
0
Source

Use this skill when users ask about benchmarking Clojure code, measuring performance, profiling execution time, or using the criterium library. Covers the 0.5.x API including bench macro, bench plans, viewers, domain analysis, and argument generation.

Install

mkdir -p .claude/skills/criterium && curl -L -o skill.zip "https://mcp.directory/api/skills/download/9362" && unzip -o skill.zip -d .claude/skills/criterium && rm skill.zip

Installs to .claude/skills/criterium

About this skill

Criterium

Statistically rigorous benchmarking for Clojure that accounts for JVM warmup, garbage collection, and measurement overhead.

Overview

Criterium is the standard benchmarking library for Clojure. Unlike naive timing approaches, it provides:

  • JVM-aware measurement - Handles JIT warmup and GC interference
  • Statistical rigor - Bootstrap confidence intervals, outlier detection
  • Multiple output formats - Text, structured data, interactive charts

Library: org.hugoduncan/criterium Current Version: 0.5.x (alpha) License: EPL-1.0

Note: The 0.4.x API (criterium.core/bench) is deprecated. Use criterium.bench/bench for all new code.

Quick Start

(require '[criterium.bench :as bench])

(bench/bench (+ 1 1))

Output:

      Elapsed Time: 2.15 ns  3σ [2.08 2.22]  min 2.07
Outliers (outliers / samples): low-severe 0 (0.0%), low-mild 0 (0.0%), high-mild 3 (1.5%), high-severe 0 (0.0%)
Sample Scheme: 200 samples with batch-size 4651 (930200 evaluations)

The output shows:

  • Mean time (2.15 ns) with 3-sigma confidence bounds
  • Outlier counts by category (low/high, mild/severe)
  • Sample scheme - how measurements were collected

Core Concepts

Criterium uses a three-stage pipeline:

Collection → Analysis → View
  1. Collection - Gather raw timing samples using collectors
  2. Analysis - Apply statistical computations (mean, bootstrap CI, outliers)
  3. View - Format and present results through viewers

The Measured Abstraction

The bench macro wraps your expression in a measured - a benchmarkable unit that:

  • Prevents constant folding by hoisting arguments
  • Supports batched evaluation for fast expressions
  • Provides zero-allocation measurement

You rarely interact with measured directly, but it enables advanced patterns like argument generation. See Argument Generation for explicit usage with test.check generators.

Basic Benchmarking

The bench Macro

(bench/bench expr & options)

Returns the expression's value. Benchmark data available via (bench/last-bench).

Common Options

;; Change output format
(bench/bench (sort data) :viewer :pprint)

;; Use a specific bench plan
(bench/bench (sort data) :bench-plan criterium.bench-plans/distribution-analysis)

;; Limit benchmark duration
(bench/bench (sort data) :limit-time-s 5)

;; Collect allocation data (requires native agent)
(bench/bench (sort data) :with-allocation-trace true)

Using Local Bindings

The bench macro captures local bindings from the enclosing scope:

(let [data (vec (range 1000))]
  (bench/bench (reduce + data)))

Reading Output

Default output fields:

FieldMeaning
Elapsed TimeMean with 3σ bounds and minimum
OutliersCount by category (low/high, mild/severe)
Sample SchemeSamples × batch-size = total evaluations

Accessing Results Programmatically

(bench/bench (reduce + (range 100)))

;; Get full results
(bench/last-bench)

;; Extract specific values
(require '[criterium.util.helpers :as util])
(util/stats-value (:data (bench/last-bench)) :stats :elapsed-time :mean)

Bench Plans

Bench plans configure what analysis and output criterium produces. The default plan handles most cases.

default

Used automatically. Provides:

  • JIT warmup phase
  • Bootstrap confidence intervals
  • Outlier detection
  • KDE density estimation (for multimodal warnings)

histogram

Non-parametric distribution analysis with histogram visualization:

(require '[criterium.bench-plans :as plans])

(bench/bench (my-function)
             :bench-plan plans/histogram)

Includes:

  • Histogram with Knuth optimal binning
  • KDE density estimation
  • Mode detection for multimodal distributions

distribution-analysis

Parametric distribution fitting for understanding timing variability:

(bench/bench (my-function)
             :bench-plan plans/distribution-analysis)

Adds:

  • Distribution fitting (gamma, log-normal, Weibull)
  • Shape statistics (skewness, kurtosis)
  • Goodness-of-fit tests
  • Q-Q plots (with appropriate viewer)

Custom Plans

Plans are maps with :analyse and :view vectors:

{:collector-config {...}
 :analyse [:transform-log :outliers [:stats {}] :bootstrap-stats]
 :view [:stats :bootstrap-stats :outlier-counts]}

Viewers

Viewers control output format. Set per-call or globally.

:print (Default)

Human-readable text to stdout:

(bench/bench (+ 1 1))  ; uses :print

:pprint

Structured Clojure data, useful for programmatic access:

(bench/bench (+ 1 1) :viewer :pprint)

:portal

Interactive charts and tables in Portal:

;; Setup: connect Portal to tap>
(require '[portal.api :as p])
(def portal (p/open))
(add-tap #'p/submit)

;; Use portal viewer
(bench/bench (+ 1 1) :viewer :portal)

Provides interactive histograms, KDE plots, and tabular data.

:kindly

For Clay/Clerk notebooks with Vega-Lite charts:

(bench/set-default-viewer! :kindly)
(bench/bench (+ 1 1))

Outputs Kindly-annotated data structures rendered as tables and charts.

Setting Default Viewer

;; Set for all subsequent bench calls
(bench/set-default-viewer! :kindly)

;; Check current default
(bench/default-viewer)

Domain Analysis

Domain analysis benchmarks across a parameter space rather than at a single point. Use it for:

  • Comparing implementations at multiple input sizes
  • Analyzing algorithmic complexity (O(n), O(n log n), etc.)
  • Understanding scaling behavior

Basic Usage

(require '[criterium.domain :as domain]
         '[criterium.domain.builder :as builder]
         '[criterium.domain-plans :as domain-plans])

;; Benchmark sorting across input sizes
(domain/bench
 (domain/domain-expr
  [n (builder/log-range 10 1000 5)]
  (sort (vec (range n)))))

The domain-expr macro defines axes (parameter ranges) and expressions to benchmark. The bench function runs benchmarks at each coordinate and analyzes results.

Comparing Implementations

Use a map body in domain-expr to compare implementations:

(domain/bench
 (domain/domain-expr
  [n (builder/log-range 100 10000 5)]
  {:sort    (sort (vec (range n)))
   :sort-by (sort-by identity (vec (range n)))})
 :domain-plan domain-plans/implementation-comparison)

Output shows the baseline (first implementation) in absolute values and others as relative factors.

Complexity Analysis

Fit O(log n), O(n), O(n log n), O(n²) models:

(domain/bench
 (domain/domain-expr
  [n (builder/n-log-n-range 10 10000 7)]
  (sort (vec (range n))))
 :domain-plan domain-plans/complexity-analysis)

Use n-log-n-range for better sampling when expecting O(n log n) complexity.

Range Generators

FunctionUse Case
log-rangeWide range coverage (10 to 10000)
linear-rangeUniform sampling
n-log-n-rangeO(n log n) algorithms
powers-of-2Binary scaling patterns

Domain Plans

PlanPurpose
extract-metricsDefault - shows all metrics
implementation-comparisonCompare implementations with factors
complexity-analysisFit complexity models

Options

(domain/bench
 (domain/domain-expr ...)
 :domain-plan domain-plans/complexity-analysis
 :reporter nil                        ; Silent (no progress dots)
 :bench-options {:limit-time-s 2})    ; Per-benchmark time limit

Argument Generation

Generate diverse inputs for each benchmark iteration using test.check generators.

Dependency: org.hugoduncan/criterium.arg-gen (separate artifact)

;; deps.edn
{:deps {org.hugoduncan/criterium.arg-gen {:mvn/version "0.5.x"}}}

The measured Macro

(require '[criterium.arg-gen :as arg-gen]
         '[clojure.test.check.generators :as gen])

;; Basic usage - each iteration gets fresh generated values
(bench/bench-measured
 (bench/options->bench-plan)
 (arg-gen/measured
  [n gen/small-integer]
  (* n n)))

Multiple Bindings

Bindings are processed left-to-right, with earlier bindings available to later generators. This enables dependent generation where one value determines another:

(arg-gen/measured
 [n (gen/choose 10 100)                    ; n bound first
  coll (gen/vector gen/small-integer n)]   ; n used to size the vector
 (reduce + coll))

Options

;; Control generator size (affects sized generators like gen/vector)
(arg-gen/measured {:size 50}
 [coll (gen/vector gen/small-integer)]
 (sort coll))

;; Reproducible generation with seed
(arg-gen/measured {:seed 12345}
 [n gen/small-integer]
 (* n n))

Common Patterns

;; String processing
(arg-gen/measured
 [s gen/string-alphanumeric]
 (clojure.string/upper-case s))

;; Collection operations
(arg-gen/measured {:size 100}
 [v (gen/vector gen/small-integer)]
 (sort v))

;; Map operations
(arg-gen/measured {:size 20}
 [m (gen/map gen/keyword gen/small-integer)]
 (vals m))

Best Practices

JVM Warmup

The JIT compiler optimizes code during execution. Criterium handles warmup automatically, but be aware:

  • First benchmark in a session may be slower (class loading, JIT)
  • Run benchmarks multiple times if results seem inconsistent
  • The default plan includes warmup phases

Avoiding Measurement Pitfalls

Dead code elimination: The JVM may optimize away computations with unused results. Criterium prevents this by consuming return values, but avoid:

;; BAD - side-effect only, result discarded
(bench/bench (do (sort data) nil))

;; GOOD - return the result
(bench/bench (sort data))

Side effects: Benchmarks with side effects (I/O, mutation) may not measure what you intend:

;; BAD - file I/O dominates timing
(bench/ben

---

*Content truncated.*

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

1,4071,302

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

1,2201,024

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

9001,013

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

958658

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

970608

pdf-to-markdown

aliceisjustplaying

Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.

1,033496

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.