Skip to content

perf: optimize header parsing and encoding - #234

Open
geeknoid wants to merge 1 commit into
hyperium:masterfrom
geeknoid:master
Open

perf: optimize header parsing and encoding#234
geeknoid wants to merge 1 commit into
hyperium:masterfrom
geeknoid:master

Conversation

@geeknoid

Copy link
Copy Markdown

Reduce parser, iterator, and formatter work without changing the public API.

Optimizations:

  • Parse Content-Length and shared second values directly from bytes, with an overflow-free short-number path and checked fallback.
  • Remove the redundant HeaderValue clone from Host decoding.
  • Specialize quote-free Cache-Control splitting, fold directives directly, and emit directives without a temporary option array.
  • Parse Content-Range with byte delimiters and direct integer conversion.
  • Parse Range bounds from bytes, streamline satisfiable-range iteration, and consume constructed Strings without copying.
  • Use the standard byte-search implementation for ETag validation and scan valid ETag lists once.
  • Replace the STS iterator pipeline with a direct byte parser.
  • Use byte suffix and prefix scans for Transfer-Encoding and Content-Disposition queries.
  • Scan Referrer-Policy values backward to find the last recognized policy.
  • Parse Cookie pairs in one pass with documented checked invariants around the retained unchecked slices.
  • Preallocate formatting Strings and move them into HeaderValue without copying.
  • Add matching 49-case Gungraun and nightly wall-clock benchmark suites.

Benchmark results:

Benchmark Instructions before Instructions after Wall ns before Wall ns after
Content-Length decode 354 236 14.59 6.89
Age decode 254 193 7.62 3.92
Host decode 790 486 50.68 44.56
Cache-Control decode 2121 1451 163.96 130.64
Cache-Control quoted decode 2628 2366 266.87 174.87
Cache-Control 16-directive decode 6314 5364 528.41 686.60
Content-Range decode 1405 528 91.59 38.48
STS decode 1684 1182 107.53 72.70
STS quoted decode 1741 1356 111.65 92.73
Referrer-Policy decode 2768 1556 200.70 151.34
ETag 32-byte decode 407 369 35.95 37.97
ETag 64-byte decode 567 403 51.47 40.37
ETag 128-byte decode 887 471 79.86 40.85
ETag 256-byte decode 1527 607 115.84 51.63
Transfer-Encoding single query 425 282 25.45 13.67
Transfer-Encoding list query 683 515 57.61 29.59
If-Match single query 1425 807 97.39 49.73
If-Match list query 2333 1392 162.46 88.20
Range satisfiable iteration 2692 1547 222.45 117.73
Cookie lookup 3418 2080 245.11 146.14
Cookie length 3248 2038 222.18 126.66
Content-Disposition query 1245 1104 78.34 61.66
Range construction 1099 1032 97.22 91.62
Cache-Control encode 2114 1610 214.40 125.50
Cache-Control all-directive encode 6576 5685 595.82 588.73
STS encode 1732 1416 184.39 116.87
Content-Range encode 2256 1928 216.36 151.52

Instruction counts are isolated Callgrind measurements. Wall-clock values are representative nightly libtest estimates and are inherently noisier.

Reduce parser, iterator, and formatter work without changing the public API.

Optimizations:
- Parse Content-Length and shared second values directly from bytes, with an overflow-free short-number path and checked fallback.
- Remove the redundant HeaderValue clone from Host decoding.
- Specialize quote-free Cache-Control splitting, fold directives directly, and emit directives without a temporary option array.
- Parse Content-Range with byte delimiters and direct integer conversion.
- Parse Range bounds from bytes, streamline satisfiable-range iteration, and consume constructed Strings without copying.
- Use the standard byte-search implementation for ETag validation and scan valid ETag lists once.
- Replace the STS iterator pipeline with a direct byte parser.
- Use byte suffix and prefix scans for Transfer-Encoding and Content-Disposition queries.
- Scan Referrer-Policy values backward to find the last recognized policy.
- Parse Cookie pairs in one pass with documented checked invariants around the retained unchecked slices.
- Preallocate formatting Strings and move them into HeaderValue without copying.
- Add matching 49-case Gungraun and nightly wall-clock benchmark suites.

Benchmark results:

| Benchmark | Instructions before | Instructions after | Wall ns before | Wall ns after |
|---|---:|---:|---:|---:|
| Content-Length decode | 354 | 236 | 14.59 | 6.89 |
| Age decode | 254 | 193 | 7.62 | 3.92 |
| Host decode | 790 | 486 | 50.68 | 44.56 |
| Cache-Control decode | 2121 | 1451 | 163.96 | 130.64 |
| Cache-Control quoted decode | 2628 | 2366 | 266.87 | 174.87 |
| Cache-Control 16-directive decode | 6314 | 5364 | 528.41 | 686.60 |
| Content-Range decode | 1405 | 528 | 91.59 | 38.48 |
| STS decode | 1684 | 1182 | 107.53 | 72.70 |
| STS quoted decode | 1741 | 1356 | 111.65 | 92.73 |
| Referrer-Policy decode | 2768 | 1556 | 200.70 | 151.34 |
| ETag 32-byte decode | 407 | 369 | 35.95 | 37.97 |
| ETag 64-byte decode | 567 | 403 | 51.47 | 40.37 |
| ETag 128-byte decode | 887 | 471 | 79.86 | 40.85 |
| ETag 256-byte decode | 1527 | 607 | 115.84 | 51.63 |
| Transfer-Encoding single query | 425 | 282 | 25.45 | 13.67 |
| Transfer-Encoding list query | 683 | 515 | 57.61 | 29.59 |
| If-Match single query | 1425 | 807 | 97.39 | 49.73 |
| If-Match list query | 2333 | 1392 | 162.46 | 88.20 |
| Range satisfiable iteration | 2692 | 1547 | 222.45 | 117.73 |
| Cookie lookup | 3418 | 2080 | 245.11 | 146.14 |
| Cookie length | 3248 | 2038 | 222.18 | 126.66 |
| Content-Disposition query | 1245 | 1104 | 78.34 | 61.66 |
| Range construction | 1099 | 1032 | 97.22 | 91.62 |
| Cache-Control encode | 2114 | 1610 | 214.40 | 125.50 |
| Cache-Control all-directive encode | 6576 | 5685 | 595.82 | 588.73 |
| STS encode | 1732 | 1416 | 184.39 | 116.87 |
| Content-Range encode | 2256 | 1928 | 216.36 | 151.52 |

Instruction counts are isolated Callgrind measurements. Wall-clock values are representative nightly libtest estimates and are inherently noisier.
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.

1 participant