Skip to content

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.