Skip to content

⚡ perf(core): shrink tokenizer and DOM state#640

Merged
gaborbernat merged 6 commits into
tox-dev:mainfrom
gaborbernat:simple-parser
Jul 11, 2026
Merged

⚡ perf(core): shrink tokenizer and DOM state#640
gaborbernat merged 6 commits into
tox-dev:mainfrom
gaborbernat:simple-parser

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Jul 11, 2026

Copy link
Copy Markdown
Member

Streaming consumers that only need tag names and text still pay to allocate attribute data. DOM parsing duplicates known tag names and allocates unused query storage.

capture_attributes=False removes the first cost. Compact text nodes and shared tag storage reduce the rest; attribute metadata and source spans use packed allocations, while query caches materialize on demand. With a 43.8 MB PyPI index snapshot, anchor extraction improves 7.2% and DOM parsing improves 8.8%; traced peak memory falls 14.0% and peak RSS falls 11.2%. Generated documentation tables record the changes across existing build and serialization cases.

Paired PGO runs cover every path touched by the patch, from builders and parsing through lossless output and XSLT. The percentages above come from quiet runs. Later host contention produced high-variance rows, which do not inform the comparison.

Large flat documents paid for attribute data consumers did not use. DOM
construction also repeated allocations for tags and per-node caches.

Add an opt-in tag-and-text tokenizer path and compact shared storage.
Preserve the default token contract while reducing parser allocations.
@gaborbernat gaborbernat added enhancement New feature or request area:parser Tokenizer / tree construction labels Jul 11, 2026
@gaborbernat gaborbernat self-assigned this Jul 11, 2026
pre-commit-ci Bot and others added 3 commits July 11, 2026 14:11
Linux C11 builds did not expose SSIZE_MAX through PyMem_New, and
clang-tidy rejected the tagged text span's integer-to-pointer cast.

Allocate the fixed-size caches by byte count and copy the tagged value into
the pointer field.
@codspeed-hq

codspeed-hq Bot commented Jul 11, 2026

Copy link
Copy Markdown

Merging this PR will improve performance by 8.79%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 12 improved benchmarks
✅ 81 untouched benchmarks
⏩ 18 skipped benchmarks1

Performance Changes

Benchmark BASE HEAD Efficiency
test_feature[tables-spec] 443.2 µs 388.3 µs +14.14%
test_feature[set-text] 539.2 µs 482.3 µs +11.79%
test_feature[set-html] 562.9 µs 505.9 µs +11.27%
test_feature[edit] 661.7 µs 601.9 µs +9.94%
test_feature[select-has] 216.4 µs 197.4 µs +9.66%
test_feature[links-rewrite] 736.9 µs 673.7 µs +9.38%
test_feature[chain] 670.5 µs 614.9 µs +9.04%
test_feature[xpath] 716.3 µs 660 µs +8.53%
test_feature[conformance] 1.2 ms 1.1 ms +6.02%
test_feature[links-extract] 1.3 ms 1.2 ms +5.59%
test_feature[observe] 1,031.3 µs 978.4 µs +5.41%
test_feature[treewalk] 1.1 ms 1.1 ms +5.08%

Tip

Curious why this is faster? Comment @codspeedbot explain why this is faster on this PR, or directly use the CodSpeed MCP with your agent.


Comparing gaborbernat:simple-parser (329eb40) with main (ecd53e1)

Open in CodSpeed

Footnotes

  1. 18 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@gaborbernat gaborbernat marked this pull request as ready for review July 11, 2026 20:31
@gaborbernat gaborbernat merged commit 01daa69 into tox-dev:main Jul 11, 2026
51 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:parser Tokenizer / tree construction enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant