Skip to content

refactor(h1): delete the unused SIMD header scan and stop advertising a SIMD parser (celeris#424) - #697

Merged
FumingPower3925 merged 3 commits into
mainfrom
fix/424-remove-dead-simd-header-scan
Sep 27, 2026
Merged

FumingPower3925 merged 3 commits into
mainfrom
fix/424-remove-dead-simd-header-scan

Conversation

@FumingPower3925

@FumingPower3925 FumingPower3925 commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

#424 asks CI to exercise the arm64 NEON header parser. That routine, findHeaderEnd (protocol/h1/findheader_*), has had no production caller since 96581bc (#359, 2026-06-17). That is a month before #424 was filed (2026-07-20). This PR resolves #424 in v1.6.0 by removing the dead code and the README claim built on it. Adding CI coverage for code no request runs would have been the wrong fix.

Fixes #424

Evidence

The scripts and outputs are in evidence/celeris-673-679-653-424/lane-20260926/424/ (per-finding index for review round 2: ROUND2.md):

  • callers-at-base.sh / .txt
  • build-after-removal.sh / .txt
  • control-caller-detected.sh / .txt
  • round2-checks.sh and its four logs
  1. Callers at 9f4d89b.
    • git grep -w findHeaderEnd, in non-test files, finds only these:
      • the three declarations (findheader_{amd64,arm64,generic}.go)
      • the two asm TEXT symbols and their header comments
      • one comment in parser.go
    • A call-site query (the name followed by (, excluding the func lines) finds none. No go:linkname names it.
  2. Positive controls for that query.
  3. The build after the deletion.
    • go build ./... and go vet ./protocol/... pass for linux/amd64, linux/arm64, linux/386, linux/riscv64, darwin/amd64 and darwin/arm64. Together these cover every architecture that had an implementation: asm on amd64/arm64, the generic loop on the rest.
    • go test -v ./protocol/h1 gives 140 PASS, 0 FAIL, 0 SKIP (again at 5ca6f6e: round2-h1-vet-and-v.log).
    • go mod tidy -diff is clean at 5ca6f6e: rc 0, no diff (round2-tidy-diff.log).
    • golangci-lint v2.13.2 (CI's Lint job pins v2.13), run ./... at 5ca6f6e: 0 issues natively (round2-golangci-native.log) and with GOOS=linux (round2-golangci-linux.log). The CI Lint job of the same head also reports 0 issues in all five of its lint steps (run 36254991605, job 108439961458; ci-36254991605-lint.log).
  4. Control. With a call to findHeaderEnd put back into parser.go, the build fails on amd64 and arm64 with undefined: findHeaderEnd, so the compile check does see a caller.

Changes

  • Deleted protocol/h1/findheader{,_amd64,_arm64,_generic}.go, findheader_amd64.s and findheader_arm64.s. These were the only assembly in the repository.
  • Deleted the five TestFindHeaderEnd_* tests and the two BenchmarkFindHeaderEnd* benchmarks.
  • parser.go: the comment that named the function now says "CRLFCRLF scan".
  • README.md:35: the bullet "SIMD HTTP parser — SSE2 (amd64) and NEON (arm64) with a generic SWAR fallback" becomes a Zero-copy HTTP/1.1 parser bullet. The old bullet described code that no request ran, and there was never a SWAR path. The new bullet (exact since review round 2) says:
    • The parser returns header and body slices that alias the bytes it parses, instead of copying them.
    • On epoll and io_uring, a request is parsed in place in the engine's read buffer when it arrives whole in one read, has no body or a Content-Length body, and runs inline.
    • A request that spans reads, has a chunked body, or runs on an async handler is served from a per-connection buffer instead: the H1 buffer, bodyBuf or asyncInBuf (internal/conn/h1.go: headers split across reads at :579, a fixed-length body spanning reads at :527-530 and :673, a chunked body at :633-680, an async route at :600; engine/epoll/loop.go:1281, engine/iouring/worker.go:2791).
  • protocol/h1/doc.go (review round 2): the package doc made the same "alias the connection's read buffer" claim. It now says the slices alias the buffer passed to Parser.Reset: an engine's read buffer, or a per-connection buffer the engine gathered the request into. It also listed the std engine as a consumer. std uses net/http's parser; only internal/conn (epoll, io_uring) imports protocol/h1.
  • The docs site's copy of the claim (src/pages/index.astro:75) is fixed in docs: EngineMetrics.Throughput always reads 0; the parser is not SIMD (celeris#653, celeris#424) docs#73.

No hot-path change: the deleted code was unreachable from any request.

CI run 36254991605 on 5ca6f6e: 9/9 green. Run 36241726098 on 1d00335 was also 9/9 green.

Release notes

  • Breaking change? No: every deleted symbol was unexported.

Summary by CodeRabbit

  • New Features
    • HTTP/1.1 parsing now uses a zero-copy approach: parsed headers and bodies can reference the received request data. Eligible requests received in a single read are parsed directly from the engine’s read buffer; requests spanning reads, using chunked bodies, or handled asynchronously use a per-connection buffer.
  • Documentation
    • Clarified that parsed values may reference reusable buffers and should be copied if they need to be retained across subsequent parsing on the same connection.

… a SIMD parser (celeris#424)

findHeaderEnd (protocol/h1/findheader_*: SSE2/AVX2 on amd64, NEON on
arm64, a scalar loop elsewhere) was the only assembly in the tree, and it
has had no production caller since 96581bc (#359, 2026-06-17), which
dropped the parser's upfront header-block scan as double work. #424, filed
a month later, asked CI to exercise the arm64 path of a routine nothing
calls. What remained was the routine, its own tests and benchmarks, and a
README feature bullet ("SIMD HTTP parser -- SSE2 (amd64) and NEON (arm64)
with a generic SWAR fallback") describing code that no request runs.

At 9f4d89b, a search for the name followed by "(" in non-test Go files
finds only the three declarations. The same query finds parser.go:118's
live parseHeaders call, and at 96581bc~1 it finds the removed
`if findHeaderEnd(remaining) < 0`. No go:linkname names it.

This deletes the six findheader files, the five findHeaderEnd tests and
two benchmarks, and a comment that named it. The README bullet now
describes what the parser does: header and body slices alias the read
buffer (the package doc's own claim). After the deletion, `go build ./...`
and `go vet ./protocol/...` pass for linux/{amd64,arm64,386,riscv64} and
darwin/{amd64,arm64}, which covers every architecture that had an
implementation. `go test ./protocol/h1` passes 140/140. go.mod is
unchanged (tidy -diff clean). Control: a reintroduced call fails to build
("undefined: findHeaderEnd") on amd64 and arm64.
The README bullet and the protocol/h1 package doc said header and body
slices alias "the connection's read buffer". That is true of the
parser's return values relative to the buffer it is given, not of the
engine path: epoll and io_uring hand the parser their read buffer only
for a request that arrives whole in one read, has no body or a
Content-Length body, and runs inline. A request that spans reads (its
headers gathered in the connection's H1 buffer, a fixed-length body in
bodyBuf, internal/conn/h1.go), a chunked body, or a request for an async
handler (asyncInBuf) is served from a per-connection buffer. The package
doc also listed the std engine as a consumer; std uses net/http's parser.
@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration

Configuration used: Repository: goceleris/celeris/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 441087cc-01a3-48fe-8790-9a5467336b58

📥 Commits

Reviewing files that changed from the base of the PR and between 5ca6f6e and 3a9349e.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: eb75bb2c-1c1c-4d67-8407-20eb29e13ed9

📥 Commits

Reviewing files that changed from the base of the PR and between 9f4d89b and 5ca6f6e.

📒 Files selected for processing (11)
  • README.md
  • protocol/h1/bench_test.go
  • protocol/h1/doc.go
  • protocol/h1/findheader.go
  • protocol/h1/findheader_amd64.go
  • protocol/h1/findheader_amd64.s
  • protocol/h1/findheader_arm64.go
  • protocol/h1/findheader_arm64.s
  • protocol/h1/findheader_generic.go
  • protocol/h1/parser.go
  • protocol/h1/parser_test.go
💤 Files with no reviewable changes (8)
  • protocol/h1/findheader.go
  • protocol/h1/findheader_amd64.go
  • protocol/h1/findheader_generic.go
  • protocol/h1/findheader_amd64.s
  • protocol/h1/findheader_arm64.s
  • protocol/h1/findheader_arm64.go
  • protocol/h1/bench_test.go
  • protocol/h1/parser_test.go

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The changes remove architecture-specific HTTP/1 header-scanning implementations and their tests and benchmarks. Parser documentation and the README now describe parser buffer usage, and a parser comment names parseHeaders as detecting incomplete headers.

Changes

HTTP/1 parser cleanup and buffer documentation

Layer / File(s) Summary
Header scanning and buffer documentation
protocol/h1/findheader*, protocol/h1/parser.go, protocol/h1/parser_test.go, protocol/h1/bench_test.go, protocol/h1/doc.go, README.md
The architecture-specific findHeaderEnd code and related tests and benchmarks are removed. The parser comment now refers to parseHeaders. Package documentation describes returned slices as aliases of the buffer passed to Parser.Reset, and the README describes buffer use for request parsing.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 5ca6f

No actionable issue remains from the supplied evidence; the parser cleanup is mergeable after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Issue #424 directly requires functional arm64 NEON coverage through an arm64 CI job or equivalent macOS job. This PR removes findHeaderEnd and its arm64 implementation and tests, but it does not add… Add the required arm64 or macOS CI coverage for the parser, or update and close #424 to record that removal of the parser is the accepted resolution before treating this requirement as complete.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The changed files remove the unused header scanner, its architecture-specific implementations, tests, and benchmarks. The README and protocol/h1 documentation changes describe the resulting parser b…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: removing the unused SIMD header scan and replacing the README’s SIMD parser claim.
Full details: Linked Issues check

Explanation

Issue #424 directly requires functional arm64 NEON coverage through an arm64 CI job or equivalent macOS job. This PR removes findHeaderEnd and its arm64 implementation and tests, but it does not add the required CI coverage. The removal may eliminate the untested parser, but it does not satisfy the linked issue's stated coding requirement.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@FumingPower3925

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 26, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@FumingPower3925
FumingPower3925 marked this pull request as ready for review September 27, 2026 14:21
@codspeed

codspeed Bot commented Sep 27, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 2.89%

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 63 untouched benchmarks
⏩ 5 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
❌ 4producers 127 ns 156 ns -18.59%
⚡ BenchmarkChainDeepParallel 2.4 µs 2.1 µs +15.83%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/424-remove-dead-simd-header-scan (3a9349e) with main (9aa94eb)2

Open in CodSpeed

Footnotes

  1. 5 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. ↩

  2. No successful run was found on main (a3ff192) during the generation of this report, so 9aa94eb was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

@codecov

codecov Bot commented Sep 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@FumingPower3925
FumingPower3925 merged commit a842109 into main Sep 27, 2026
16 of 17 checks passed
@FumingPower3925
FumingPower3925 deleted the fix/424-remove-dead-simd-header-scan branch September 27, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/protocol Protocol parsing / detection documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exercise the arm64 NEON header parser in CI

1 participant