Skip to content

build: skip Filter flag for non-positional predicates - #140

Merged
zhengchun merged 3 commits into
antchfx:masterfrom
thunderkatz:fix/non-positional-filter-descendant-collapsing
Sep 20, 2026
Merged

zhengchun merged 3 commits into
antchfx:masterfrom
thunderkatz:fix/non-positional-filter-descendant-collapsing

Conversation

@thunderkatz

Copy link
Copy Markdown
Contributor

processFilter always set flagsEnum.Filter on its input, which blocked the descendant-collapsing optimization in processAxis. //element[@attr] compiled to childQuery{Input: descendantQuery{}} instead of the more efficient descendantQuery{name:"element"}. The Filter flag is only needed for positional predicates where mergeQuery restructuring is needed, like for //table[1]. For non-positional predicates like //a[@href] we can drop the flag.

This change adds positionalCondition(), a lightweight AST walk that inspects the raw condition node before compilation, and gates the flag on its result. Non-positional predicates now resolve to a single descendantQuery. Added a unit test for the new function.

Benchmarking (bench functions included) showed significant time and alloc reductions for non-positional filters, and no change for positional filters.

This PR contains code written by Claude (Sonnet 4.6).

thunderkatz and others added 3 commits September 18, 2026 15:47
…ndant-collapsing

processFilter unconditionally set flagsEnum.Filter on its input, which
blocked the descendant-collapsing optimization in processAxis:
//element[@attr] compiled to childQuery{Input: descendantQuery{}} instead
of the more efficient descendantQuery{name:"element"}.

The Filter flag is only load-bearing for positional predicates (numeric
literals, position(), last(), arithmetic) where mergeQuery restructuring
is needed to give correct "first per parent" semantics for //table[1].
For non-positional predicates like //a[@href] or //div[@Class="x"] the
flag serves no purpose.

This change adds positionalCondition(), a lightweight AST walk that
inspects the raw condition node before compilation, and gates the flag
on its result. Non-positional predicates now resolve to a single
descendantQuery, reducing allocations by ~70% and execution time by ~57%
on a representative 430-node document.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zhengchun
zhengchun merged commit 487996f into antchfx:master Sep 20, 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