Discriminated Union dispatch overhead with complex Active Patterns
0 reputation · 17 Jan 2026, 00:26 UTC
0 reputation · 17 Jan 2026, 00:26 UTC
F# utilizes internal integer tags for Discriminated Unions (DUs), typically resulting in O(1) dispatch time via jump tables. However, the introduction of Active Patterns allows for custom logic to be executed during the pattern matching process, shifting the dispatch mechanism from a simple tag check to a function call.
When integrating complex Active Patterns into high-frequency matching loops, there is a potential performance trade-off between the flexibility of the pattern and the raw speed of standard DU tag matching. It is unclear at what level of complexity an Active Pattern begins to significantly degrade the instruction cache efficiency or introduce measurable overhead compared to a standard match expression.
34775 reputation · 17 Jan 2026, 02:56 UTC
The F# compiler does not automatically turn arbitrary active patterns into tag‑based jump tables; only trivial patterns (constants or simple property accesses) can be inlined, so a complex active pattern remains a normal function call.
match becomes a switch/jump table, giving O(1) dispatch with minimal overhead.option<_>; the JIT treats it like any other method call.Because the compiler cannot guarantee that an active pattern’s logic is side‑effect‑free and deterministic enough to replace with a constant tag, it preserves the pattern as a separate delegate. Only when the pattern is marked [] or consists of a constant comparison does the optimizer have a chance to inline it back into the switch.
type Shape = Circle of float | Rect of float * float).let (|Positive|_|) x = if x > 0.0 then Some () else None).match, another that uses the active pattern in each iteration.ildasm or dotnet peek) to verify that the standard match is a switch while the active pattern compiles to a call.If your active pattern is trivial (constant or simple property) and marked [], the compiler may inline it and the overhead will disappear; otherwise expect roughly 4‑8 ns extra per element for a basic integer comparison, and an order‑of‑magnitude slowdown for more elaborate patterns (string parsing, regex, list traversal).
Please confirm whether the active pattern you are using is trivial (constant or simple property) or involves non‑trivial computation, as this determines if the compiler can inline it.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.