Skip to content

perf: general performance improvements - #500

Merged
stefan-gorules merged 3 commits into
masterfrom
perf/general-performance-improvements
Aug 4, 2026
Merged

perf: general performance improvements#500
stefan-gorules merged 3 commits into
masterfrom
perf/general-performance-improvements

Conversation

@stefan-gorules

Copy link
Copy Markdown
Contributor

Leaner values

Variable internals were rebuilt for speed without new complexity: strings use an inline small-string representation (short keys and values never touch the heap, well-known keys like $ and $root are free constants), and objects use a compact insertion-ordered representation that spills to a hash map only when they grow. Small payloads now serialize deterministically. The entire core workspace is #![forbid(unsafe_code)] — an experiment with pooled allocations was measured and deliberately dropped in favor of the simpler design.

Scoped evaluation

The expression VM evaluates against a scope of locals layered over the input instead of copying and mutating environment objects. Per-run bindings like $ and $nodes no longer force copy-on-write of the whole environment or leak writes into caller-owned data, and array or scalar environments pass through untouched.

Validation without conversion

JSON Schema validation runs directly over Variable trees through a safe borrow-guard adapter — no serde conversion per validation. Validators compile once per document and travel with it, as do dictionary-resolved schemas, instead of being rebuilt on every evaluation. Fractional numbers now validate correctly against integer and numeric bounds.

Indexed decision tables

The equality index the policy engine uses for decision tables now accelerates graph tables too, from one shared implementation. Literal cells are indexed per column at compile time with wildcard and complex cells as fallback rows, so a lookup prunes non-matching rows before any expression runs. Traced runs keep the linear scan, which doubles as a permanent parity oracle, and uncompiled content transparently falls back to it.

Shared compiled content

Graph content is reference-counted end to end: sub-decision calls and repeated evaluations share one compiled artifact — opcodes, table indexes, resolved schemas, validators — instead of cloning per call. This also removes cross-thread contention, so throughput scales close to linearly with cores.

Fixes

v1 function nodes and custom nodes receive $nodes again. Expression-node $ references now have uniform aliasing semantics instead of a fixed-depth copy. The ToVariable derive works for consumers that depend only on the expression crate and for tagged enums. Cache entries first seen through synchronous loads gain their resolved schemas on first use instead of never.

Business Value

Evaluations are faster across the board — lower median latency, a much shorter tail on rule-heavy workloads, and near-linear multi-core scaling — with identical results, verified by parity tests that run the old and new paths against each other. The engine got safer at the same time: no unsafe code anywhere in core, no custom allocator requirements for embedders, and all precompiled state carries a single, predictable lifecycle with its document.

@stefan-gorules
stefan-gorules merged commit fe43b4c into master Aug 4, 2026
61 checks passed
@stefan-gorules
stefan-gorules deleted the perf/general-performance-improvements branch August 4, 2026 09:12
This was referenced Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants