Patternia Performance - v0.9.5¶
Published: October 2026
Focus: Letting the bare spellings is<T> and alt<I> reach the static variant dispatch fast path.
Overview¶
v0.9.5 stores the bare spellings is<T> and alt<I> as the same canonical
pattern types as is<T>() and alt<I>(). The dispatch optimizer and the
diagnostics only recognize the canonical types, so before this change a case
written as is<T> >> handler fell back to sequential evaluation while
is<T>() >> handler was lowered. No new dispatch algorithm was introduced and
no API changed; the two spellings now produce the same code.
Motivation¶
is<T> and alt<I> are variable templates whose values are the factory
objects is_factory<T> and alt_factory<I>. The factories derive from
type_is_pattern and type_alt_pattern, but the optimizer matches on the
exact canonical types, not on types derived from them. The bare spelling is
the shorter and more common one in user code, so the common spelling missed
the fast path that the benchmarks, which use the call form, always measured.
Change¶
| Component | Before (v0.9.4) | After (v0.9.5) |
|---|---|---|
Pattern stored for is<T> |
is_factory<T> |
type_is_pattern<T> |
Pattern stored for alt<I> |
alt_factory<I> |
type_alt_pattern<I> |
canonical_pattern_t maps the two factories to the canonical types, and
operator>> and $(...) apply it when they store a pattern. The factories
carry no state, so converting them loses nothing and behavior is unchanged.
The change lives in:
Benchmarks¶
Setup: an 8-alternative std::variant of empty-ish structs, 4096 values in a
pseudo-random but fixed order, one match(v) | PTN_ON(...) per value with a
_ fallback. Each number is the median of 15 repetitions of 200 passes over
the data; the table gives the median of three process runs. Apple M4 Pro,
Apple clang 17.0.0, -std=c++17 -O2 -DNDEBUG, headers from the v0.9.4 tag
and from this release.
| Case | v0.9.4 (ns/op) | v0.9.5 (ns/op) | Delta |
|---|---|---|---|
is<T> >> ... (bare) |
2.18 | 1.32 | -39.7% |
alt<I> >> ... (bare) |
2.10 | 1.27 | -39.4% |
is<T>() >> ... (call) |
1.31 | 1.29 | -2.1% (noise) |
alt<I>() >> ... (call) |
1.28 | 1.35 | +5.1% (noise) |
std::visit |
3.64 | 3.70 | +1.4% (noise) |
The call forms and std::visit did not change, which is what the change
predicts: they were already on the fast path, and std::visit does not use the
library at all. After the change all four Patternia spellings sit within run
noise of each other. The first process run was noticeably slower on both
versions (for example 2.94 vs 1.83 ns/op for bare is<T>), so only the
relative result between the two versions in the same run is meaningful, and
the absolute numbers depend on the machine.
These are single-machine numbers from one compiler. GCC and MSVC were not measured; the CI benchmark comparison on the pull request is the cross-check.
Outcome¶
v0.9.5 is a small performance release. Code written with the bare is<T> and
alt<I> spellings gets the same variant dispatch as the call forms, about 40%
faster on an 8-alternative variant in this measurement, and nothing else in the
dispatch strategy changes.