Repository navigation
Benchmarks
Important
There's no parser-only benchmark of Parsec against Lexbor yet. The one published number is Netweir's, it includes Python and the queries, and it should be read that way.
This page says what it measures, what's planned, and how to time Parsec yourself.
Before Parsec claims to be faster than Lexbor, it has to show it, in one process, on the same bytes. That's #2, the first item of milestone M1. Proof:
- a
bench/crate that builds Lexbor from a pinned release with CMake and calls its C API directly, next to html5ever and Parsec; - a corpus of real pages fetched by a pinned script, a generated 1 MB page and a 10 MB one, and the hostile inputs from
crates/parsec/examples/hostile.rs; - MB/s as the median of at least 30 runs, and peak memory;
- the method, the machine and the numbers on this page.
Selector matching gets the same treatment in #3: the selector battery from crates/parsec/examples/select.rs against Lexbor's lxb_selectors_find, one row per selector, so the slow ones are visible.
Until those land, this page doesn't have a Parsec-versus-Lexbor number to give you.
Parsec's parser is the one inside Netweir, a web scraping library for Python. Netweir's bench/parse.py parses a generated shop page and pulls every product's price, title and link out of it, which is the work a scraper does on every page, and reports the best of several runs. Its published results:
| 1 MB page | 10 MB page | |
|---|---|---|
| Netweir (Parsec inside) | 3.0 ms | 31 ms |
| selectolax (Lexbor inside) | 5.7 ms | 64 ms |
Measured on an Apple M-series laptop with Python 3.14.
What that does and doesn't tell you:
- It's an end-to-end number from Python: the call from Python, the parse, three CSS queries, and turning the results into Python strings, for both libraries.
- The two libraries do the queries differently. Netweir runs the whole query in Rust and hands Python a finished list of strings; selectolax returns a node object per match and the benchmark reads each one's text or attribute from Python. Part of the gap is that difference, not the parser.
- One kind of generated page, at two sizes, on one machine. It isn't a corpus.
So it says that a scraper built on Parsec does this job in about half the time of one built on selectolax. It doesn't say how Parsec's parser alone compares with Lexbor's. #2 will.
crates/parsec/examples has four small programs. Run them from the repository root in release mode (the workspace's release profile uses thin LTO and one codegen unit):
| Command | What it times |
|---|---|
cargo run --release --example parse FILE |
parse(&html, false) on the file, 300 times; prints the best time and the node count. The file is read as UTF-8 and the program panics if it isn't. |
cargo run --release --example tokenize FILE |
preprocess plus the tokenizer alone with a counting sink, 300 times; prints the best time and a count of tags, attributes and text bytes. Also UTF-8 only. |
cargo run --release --example select DIR [ROUNDS] |
Parses every .html file in DIR (decoded lossily as UTF-8), moves template contents into the tree, then runs a battery of 32 selectors over every document; prints the best of ROUNDS rounds (5 by default) and the total number of matches. |
cargo run --release --example hostile |
The eight hostile inputs described in Limits and hostile input; prints size, time and node count for each. |
For example:
curl -sL https://html.spec.whatwg.org/ -o /tmp/spec.html
cargo run --release --example parse /tmp/spec.htmlThe times exclude reading the file. They're best-of-N, which shows what the code can do on a warm cache rather than what a cold first parse costs. If you compare against another parser, give it the same bytes, the same number of runs, and the same machine, and include the cost of decoding if the other parser decodes for you.
-
Limits and hostile input, for the hostile inputs
hostile.rstimes. - Roadmap, for milestone M1, where the real comparison lives.
- Comparison with Lexbor, for everything other than speed.
Parsec is Apache-2.0 and not yet released; these pages describe main. Found something wrong here? Open an issue or ask in Discussions.
Repository · Issues · Discussions · Roadmap · Security policy · Licence