Skip to content

Improve serialization performance with memchr#740

Open
mrobinson wants to merge 1 commit into
mainfrom
serialize-memchr
Open

Improve serialization performance with memchr#740
mrobinson wants to merge 1 commit into
mainfrom
serialize-memchr

Conversation

@mrobinson
Copy link
Copy Markdown
Member

This change greatly improves the performance of serialization (up to
95% on some benchmarks) by changing the way that escaping of HTML
entities works. It uses memchar to avoid creating a chars() iterator
on the output stream. When run with the benchmark from #739, I see these
results:

serialize "lipsum.html" time:   [6.4817 µs 6.5021 µs 6.5212 µs]
                        change: [−95.179% −95.013% −94.846%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) low severe
  1 (1.00%) low mild

serialize "lipsum-zh.html"
                        time:   [2.0815 µs 2.0888 µs 2.0947 µs]
                        change: [−91.533% −90.940% −90.407%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 15 outliers among 100 measurements (15.00%)
  15 (15.00%) low severe

serialize "medium-fragment.html"
                        time:   [7.7625 µs 7.7927 µs 7.8147 µs]
                        change: [−84.424% −83.952% −83.486%] (p = 0.00 < 0.05)
                        Performance has improved.

serialize "small-fragment.html"
                        time:   [879.01 ns 886.43 ns 892.78 ns]
                        change: [−89.813% −89.711% −89.610%] (p = 0.00 < 0.05)
                        Performance has improved.

serialize "tiny-fragment.html"
                        time:   [332.13 ns 332.78 ns 333.60 ns]
                        change: [−27.768% −27.617% −27.457%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) low mild
  3 (3.00%) high mild
  1 (1.00%) high severe

serialize "strong.html" time:   [5.4946 µs 5.4988 µs 5.5030 µs]
                        change: [−0.3133% −0.0322% +0.2349%] (p = 0.83 > 0.05)
                        No change in performance detected.
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) low severe
  1 (1.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe

In this case lipsum.html deserialization time dropped from 122.81 µs
to 6.5021 µs.

This change greatly improves the performance of serialization (up to
95% on some benchmarks) by changing the way that escaping of HTML
entities works. It uses memchar to avoid creating a `chars()` iterator
on the output stream. When run with the benchmark from #739, I see these
results:

```
serialize "lipsum.html" time:   [6.4817 µs 6.5021 µs 6.5212 µs]
                        change: [−95.179% −95.013% −94.846%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) low severe
  1 (1.00%) low mild

serialize "lipsum-zh.html"
                        time:   [2.0815 µs 2.0888 µs 2.0947 µs]
                        change: [−91.533% −90.940% −90.407%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 15 outliers among 100 measurements (15.00%)
  15 (15.00%) low severe

serialize "medium-fragment.html"
                        time:   [7.7625 µs 7.7927 µs 7.8147 µs]
                        change: [−84.424% −83.952% −83.486%] (p = 0.00 < 0.05)
                        Performance has improved.

serialize "small-fragment.html"
                        time:   [879.01 ns 886.43 ns 892.78 ns]
                        change: [−89.813% −89.711% −89.610%] (p = 0.00 < 0.05)
                        Performance has improved.

serialize "tiny-fragment.html"
                        time:   [332.13 ns 332.78 ns 333.60 ns]
                        change: [−27.768% −27.617% −27.457%] (p = 0.00 < 0.05)
                        Performance has improved.
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) low mild
  3 (3.00%) high mild
  1 (1.00%) high severe

serialize "strong.html" time:   [5.4946 µs 5.4988 µs 5.5030 µs]
                        change: [−0.3133% −0.0322% +0.2349%] (p = 0.83 > 0.05)
                        No change in performance detected.
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) low severe
  1 (1.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe
```

In this case `lipsum.html` deserialization time dropped from 122.81 µs
to 6.5021 µs.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
@github-actions github-actions Bot added the V-non-breaking A non-breaking change label May 15, 2026
@mrobinson
Copy link
Copy Markdown
Member Author

I plan to extend support for this optimization to the XML serializer in a followup. In order to do that I need to make some XML benchmarks. That seems like enough to split into a separate PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

V-non-breaking A non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant