Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimise allocations in ParseAccept #5

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

charleskorn
Copy link

@charleskorn charleskorn commented Mar 3, 2023

This PR contains two small optimisations that overall produce the following improvements to ParseAccept:

goos: darwin
goarch: arm64
pkg: github.com/munnerz/goautoneg
                                                                                                          │ original.txt │              new.txt               │
                                                                                                          │    sec/op    │   sec/op     vs base               │
ParseAccept/#00-10                                                                                          24.445n ± 0%   6.540n ± 1%  -73.25% (p=0.002 n=6)
ParseAccept/application/json-10                                                                              90.67n ± 1%   66.41n ± 1%  -26.75% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                   152.7n ± 1%   123.7n ± 1%  -18.99% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                             214.5n ± 0%   164.5n ± 1%  -23.29% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10    636.6n ± 1%   528.9n ± 0%  -16.92% (p=0.002 n=6)

                                                                                                          │ original.txt │                new.txt                 │
                                                                                                          │     B/op     │    B/op     vs base                    │
ParseAccept/#00-10                                                                                            24.00 ± 0%    0.00 ± 0%  -100.00% (p=0.002 n=6)
ParseAccept/application/json-10                                                                               72.00 ± 0%   48.00 ± 0%   -33.33% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                   120.00 ± 0%   80.00 ± 0%   -33.33% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                             168.00 ± 0%   80.00 ± 0%   -52.38% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10     456.0 ± 0%   240.0 ± 0%   -47.37% (p=0.002 n=6)

                                                                                                          │ original.txt │                new.txt                 │
                                                                                                          │  allocs/op   │ allocs/op   vs base                    │
ParseAccept/#00-10                                                                                            1.000 ± 0%   0.000 ± 0%  -100.00% (p=0.002 n=6)
ParseAccept/application/json-10                                                                               2.000 ± 0%   1.000 ± 0%   -50.00% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                    2.000 ± 0%   1.000 ± 0%   -50.00% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                              3.000 ± 0%   1.000 ± 0%   -66.67% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10     5.000 ± 0%   1.000 ± 0%   -80.00% (p=0.002 n=6)

The first optimisation (9895b45) uses golang.org/x/exp/slices.SortFunc instead of sort.Sort. This requires Go 1.18+ as it uses generics.

The second optimisation (7248a2f) drops parsing of parameters. According to the spec, this is no longer widely used. Dropping this parsing has the benefit of not needing to allocate for the Accept.Params field. Headers that contain parameters will still be correctly parsed.

goos: darwin
goarch: arm64
pkg: github.com/munnerz/goautoneg
                                                                                                          │ original.txt │       step-2-slices-sort.txt       │
                                                                                                          │    sec/op    │   sec/op     vs base               │
ParseAccept/#00-10                                                                                          24.445n ± 0%   6.524n ± 0%  -73.31% (p=0.002 n=6)
ParseAccept/application/json-10                                                                              90.67n ± 1%   65.66n ± 0%  -27.58% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                   152.7n ± 1%   125.3n ± 0%  -17.94% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                             214.5n ± 0%   188.1n ± 0%  -12.28% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10    636.6n ± 1%   615.6n ± 1%   -3.30% (p=0.002 n=6)
geomean                                                                                                      135.8n        90.93n       -33.05%

                                                                                                          │ original.txt │         step-2-slices-sort.txt         │
                                                                                                          │     B/op     │    B/op     vs base                    │
ParseAccept/#00-10                                                                                            24.00 ± 0%    0.00 ± 0%  -100.00% (p=0.002 n=6)
ParseAccept/application/json-10                                                                               72.00 ± 0%   48.00 ± 0%   -33.33% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                   120.00 ± 0%   96.00 ± 0%   -20.00% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                              168.0 ± 0%   144.0 ± 0%   -14.29% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10     456.0 ± 0%   432.0 ± 0%    -5.26% (p=0.002 n=6)
geomean                                                                                                       109.7                    ?                      ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean

                                                                                                          │ original.txt │         step-2-slices-sort.txt         │
                                                                                                          │  allocs/op   │ allocs/op   vs base                    │
ParseAccept/#00-10                                                                                            1.000 ± 0%   0.000 ± 0%  -100.00% (p=0.002 n=6)
ParseAccept/application/json-10                                                                               2.000 ± 0%   1.000 ± 0%   -50.00% (p=0.002 n=6)
ParseAccept/application/json,text/plain-10                                                                    2.000 ± 0%   1.000 ± 0%   -50.00% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                              3.000 ± 0%   2.000 ± 0%   -33.33% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10     5.000 ± 0%   4.000 ± 0%   -20.00% (p=0.002 n=6)
geomean                                                                                                       2.268                    ?                      ¹ ²
¹ summaries must be >0 to compute geomean
² ratios must be >0 to compute geomean
According to https://httpwg.org/specs/rfc9110.html#field.accept,
parsing parameters has been removed from the spec as it's no longer
widely used.

Removing parameter parsing means that Accept will only ever allocate
once.

Compared to the previous commit:

goos: darwin
goarch: arm64
pkg: github.com/munnerz/goautoneg
                                                                                                          │ step-2-slices-sort.txt │     step-4-without-params.txt      │
                                                                                                          │         sec/op         │   sec/op     vs base               │
ParseAccept/#00-10                                                                                                     6.524n ± 0%   6.540n ± 1%        ~ (p=0.056 n=6)
ParseAccept/application/json-10                                                                                        65.66n ± 0%   66.41n ± 1%   +1.15% (p=0.009 n=6)
ParseAccept/application/json,text/plain-10                                                                             125.3n ± 0%   123.7n ± 1%   -1.28% (p=0.026 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                                       188.1n ± 0%   164.5n ± 1%  -12.54% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10              615.6n ± 1%   528.9n ± 0%  -14.08% (p=0.002 n=6)
geomean                                                                                                                90.93n        85.90n        -5.54%

                                                                                                          │ step-2-slices-sort.txt │      step-4-without-params.txt      │
                                                                                                          │          B/op          │    B/op     vs base                 │
ParseAccept/#00-10                                                                                                    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=6) ¹
ParseAccept/application/json-10                                                                                       48.00 ± 0%     48.00 ± 0%        ~ (p=1.000 n=6) ¹
ParseAccept/application/json,text/plain-10                                                                            96.00 ± 0%     80.00 ± 0%  -16.67% (p=0.002 n=6)
ParseAccept/application/json;q=0.9,text/plain-10                                                                     144.00 ± 0%     80.00 ± 0%  -44.44% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10             432.0 ± 0%     240.0 ± 0%  -44.44% (p=0.002 n=6)
geomean                                                                                                                          ²               -23.78%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                                                                                          │ step-2-slices-sort.txt │      step-4-without-params.txt      │
                                                                                                          │       allocs/op        │ allocs/op   vs base                 │
ParseAccept/#00-10                                                                                                    0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=6) ¹
ParseAccept/application/json-10                                                                                       1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=6) ¹
ParseAccept/application/json,text/plain-10                                                                            1.000 ± 0%     1.000 ± 0%        ~ (p=1.000 n=6) ¹
ParseAccept/application/json;q=0.9,text/plain-10                                                                      2.000 ± 0%     1.000 ± 0%  -50.00% (p=0.002 n=6)
ParseAccept/application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5-10             4.000 ± 0%     1.000 ± 0%  -75.00% (p=0.002 n=6)
geomean                                                                                                                          ²               -34.02%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean
@pracucci
Copy link

pracucci commented Jun 7, 2024

This change breaks https://github.com/prometheus/common which is using Params and vendoring this library since prometheus/common#625

@pracucci
Copy link

pracucci commented Jun 7, 2024

This change breaks https://github.com/prometheus/common which is using Params and vendoring this library since prometheus/common#625

See #6 for the same PR, but re-introducing Params (so only 1 out of the 2 optimizations).

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