release: PureXML 0.4.1 (#290)

Stamp the post-0.4.0 XPath performance work as 0.4.1: the descendant
single-accumulator traversal, the descendant and attribute node-test fusions,
the shared evaluation Environment, and the compiled per-query node test. xpath
goes from ~5.5x to ~1.3x slower than libxml2 across these passes, with identical
results (each correctness-sensitive change differential-tested and adversarially
reviewed).
This commit is contained in:
Mihaela Mihaljevic 2026-06-25 10:45:19 +02:00 committed by GitHub
parent f6a093fe4b
commit c62e02f49d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.4.1] - 2026-06-25
### Changed
- XPath compiles a step's node test once per query instead of re-evaluating its fixed structure on every node. The descendant and attribute walks tested each candidate through a closure that called `matchesTree`/`matchesAttribute` with the step's `NodeTest` and the evaluation `namespaces` dictionary, so the dominant traversal of a `//name`-style query passed (and reference-counted) the namespace dictionary by value on every one of tens of thousands of nodes. `compiledTreeTest`, `compiledAttributeTest`, and `compiledNodeTest` resolve the parts that do not change as the walk moves (the axis principal kind, whether eval-time bindings are in effect, the prefix-wildcard shape of the test name) exactly once, returning a tight per-node closure that captures only the local name. The selected nodes are identical to the unfused `matchesTree`/`matchesAttribute`/`matches` path. Measured `xpath` ~35% faster on the 20k-item generated corpus via a same-machine-state A/B (from ~2.0x to ~1.3x slower than libxml2). Guarded by `XPathCompiledNodeTestTests`, an exhaustive differential over every node, test, axis, and binding asserting the compiled closures equal the functions they specialize, and confirmed by an adversarial equivalence review.