Performance and benchmarks
Bramble tracks memory allocations and performance regressions with a dedicated regression suite in benchmark/benchmarks.jl. All measurements below are run on 1,000,000 grid points per dimension setup (e.g. $1000 \times 1000$ in 2D, $100 \times 100 \times 100$ in 3D).
Comparative timings and allocations
Each chart below tracks one benchmark group across all 12 recorded baselines, in chronological release order, against the earliest run (v2.0.0) as the reference. Where a group's operations span more than a 20× range, the y-axis shows time relative to that reference instead of absolute time, so a cheap operation isn't flattened onto the same line as an expensive one. Hover any point for its exact time, Julia version, thread count, allocation count, and memory.
Baselines before v2.9.0 were recorded with 1 thread; from v2.9.0 onward, 4 threads. Entries on the Parallel() backend are not comparable across that line, and the charts mark it with a dotted rule: at one thread the threaded code path runs its serial branch, so those entries measured task-spawn overhead rather than parallelism. Serial entries are unaffected.
Operators 2D
The finite-difference stencil engine on a 1000×1000 grid: the difference operator along the grid's contiguous storage direction (D₋ₓ) versus across it (D₋ᵧ), which access memory very differently and so can perform very differently.
Operators 3D
The same stencil engine in 3D (D₋₂), together with the inner product innerₕ and the full gradient ∇₋ₕ.
Jumps and averages
Jump and average operators across cell interfaces, in 2D and 3D.
Inner products 2D
The reduction path — inner products and norms — including the seminorm's sum over directions.
Restriction
Point interpolation (Rₕ!) and cell-averaging (avgₕ!), compared across the Serial() (the allocation-free default) and Parallel() backends, split by dimension.
Composite
A composite (multi-component) operator, which dispatches per component and calls the engine once per component with a view rather than once with a plain vector.
Construction
Mesh and grid-space construction, including the quadrature weights gridspace builds internally.
Startup and latency
Time to first using Bramble and first operator call — compilation latency, not steady-state performance.
Forms
Linear and bilinear form assembly, across 1D/2D and the Serial()/Parallel() backends.
Jacobian sparsity
8 benchmarks in this group, across 12 recorded releases.
Precision 1D
The same 1D workload — restriction, assembly, inner product — repeated in Float32, Float64, and Double64, split by precision since Double64 (software arithmetic) is an order of magnitude slower.
How to add new benchmark runs
To record performance on a new commit or after an optimization pass, run:
julia --project=benchmark benchmark/benchmarks.jl --save benchmark/baselines/baseline_$(git rev-parse --short HEAD).jsonRebuilding the documentation (julia -e 'using Pkg; Pkg.activate("docs"); include("docs/make.jl")') will automatically discover all baseline_*.json files and append new comparison columns, delta calculations, and charts.