Skip to content

Merge remote-tracking branch 'origin/dev/v2.1' into perf/ownership-label-injection-streaming - #484

Merged
scttbnsn merged 2 commits into
dev/v2.1from
perf/ownership-label-injection-streaming
Sep 5, 2026
Merged

Merge remote-tracking branch 'origin/dev/v2.1' into perf/ownership-label-injection-streaming#484
scttbnsn merged 2 commits into
dev/v2.1from
perf/ownership-label-injection-streaming

Conversation

@scttbnsn

@scttbnsn scttbnsn commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

The ownership middleware parsed every create body it stamps an owner label into twice. filter.RejectDuplicateCaseVariantJSONKeys decoded the raw bytes into a map[string]any, walked it for case-variant sibling keys and threw it away, and then mutateJSONBody decoded the identical bytes again to do the injection. This runs the ambiguity check against the tree the mutation already has, through a new filter.RejectDuplicateCaseVariantJSONValue that wraps the same unexported walk the byte-taking form already delegated to, so the verdict is unchanged and there's one decode instead of two. On a realistic 3.9 KB POST /containers/create body that's 101.45us to 64.26us per request (-37%), 79.1 KiB to 48.4 KiB allocated (-39%), and 1415 to 808 allocations (-43%), measured with benchstat over 12 runs on each side. Nothing changes about what gets injected, when, or what bytes go upstream. The one visible difference is that a body whose JSON doesn't parse now comes back as a decode failure instead of the ambiguity check's wrapping of the same parse error.

PERF-20 asked for a different shape: decode only the top-level object into json.RawMessage values, touch the Labels member, and re-emit the other members verbatim. I built that first and measured it against the same body. It lands at 1276 allocations, because the duplicate-key check still decodes the whole body regardless, and because HostConfig and NetworkingConfig, the two members ownership has to read to collect cross-owner references, are more than half of a real create payload. Splitting the top level isn't free either, at 8.5 KiB and 92 allocations on its own even with zero-copy spans instead of RawMessage copies. Net it came out at roughly no change in allocated bytes and about -10% allocations, so I dropped it in favour of the version above and the roadmap item's Done-when needs rewriting.

TestMutateContainerCreateOwnershipBodyDecodesTheBodyOnce is the regression guard, an allocation ceiling of 1000 that sits between the old 1415 and the new 808 and fails the moment the body gets parsed twice again. TestMutateJSONBodyRejectsAmbiguousBodyBeforeMutating keeps the fail-closed rejection and its wording now that the check moved off the raw bytes. TestMutateJSONBodyReportsMalformedBodyAsADecodeFailure pins the one error path that changed, and TestMutateJSONBodyRejectsNonObjectBodies covers null, array, string, number and bool payloads. TestRejectDuplicateCaseVariantJSONValueMatchesByteForm locks the two filter entry points to one verdict across a clean body, top-level and nested case-variant duplicates, the case-sensitive data-map exemption, a struct nested under a data map, large integers, and arrays of objects. BenchmarkMutateContainerCreateOwnershipBody is where the numbers come from. go build ./..., go vet ./..., go test ./..., golangci-lint run ./... and go test -race ./internal/ownership/ ./internal/filter/ all pass, and FuzzOwnershipMutateBody and FuzzOwnershipMutateServiceBody each ran 60s clean.

CHANGELOG entry is under ### Changed in ## [Unreleased].

Changelog

✨ Added

  • Added RejectDuplicateCaseVariantJSONValue for validation of decoded JSON values.
  • Added regression tests for duplicate keys, malformed bodies, non-object bodies, single decoding, and byte/value parity.
  • Added ownership mutation benchmarks and allocation coverage.
  • Added race and non-race build helpers.

🔧 Changed

  • Reused the decoded request value during ownership-label injection.
  • Preserved injection behavior, timing, and upstream request bytes.
  • Updated the libpodNamespaceRefs validation comment.
  • Updated the unreleased changelog.

🐛 Fixed

  • Removed the second request-body decode during duplicate-key validation.
  • Reduced request time by 37%, allocated memory by 39%, and allocations by 43%.

Every request the ownership middleware injects an owner label into ran
filter.RejectDuplicateCaseVariantJSONKeys over the raw body and then
decoded the same bytes again for the mutation, so each inspected create
built two identical map[string]any trees and threw one away.

The ambiguity guard now runs against the tree the mutation already
decoded, through a new filter.RejectDuplicateCaseVariantJSONValue that
wraps the same unexported walk the byte-taking form already delegated
to. Same walk, same value, same verdict.

Measured over a realistic 3.9 KB POST /containers/create body:
101.45us -> 64.26us (-37%), 79.1 KiB -> 48.4 KiB (-39%), 1415 -> 808
allocations (-43%).

- perf(ownership): run the ambiguity check on the decoded tree
- feat(filter): add RejectDuplicateCaseVariantJSONValue
- test(ownership): guard the single decode and pin the body edge cases
- test(filter): lock the two ambiguity entry points to one verdict
@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

Deployment failed for project sockguard-website with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/codeswhat?upgradeToPro=build-rate-limit

@biggest-littlest biggest-littlest left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against the CHANGELOG entry and the diff; CI green outside the qlty/Vercel quota noise.

@ALARGECOMPANY ALARGECOMPANY left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed against the CHANGELOG entry and the diff; CI green outside the qlty/Vercel quota noise.

@scttbnsn
scttbnsn merged commit 803888c into dev/v2.1 Sep 5, 2026
15 of 21 checks passed
@scttbnsn
scttbnsn deleted the perf/ownership-label-injection-streaming branch September 5, 2026 14:53
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: ce4d72f6-3728-4bab-b3b1-d79cdee1f8ee

📥 Commits

Reviewing files that changed from the base of the PR and between 60cf77d and 00d1590.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !CHANGELOG.md
📒 Files selected for processing (8)
  • app/internal/filter/container_create.go
  • app/internal/filter/container_create_test.go
  • app/internal/ownership/bench_test.go
  • app/internal/ownership/libpod.go
  • app/internal/ownership/middleware.go
  • app/internal/ownership/middleware_test.go
  • app/internal/ownership/norace_test.go
  • app/internal/ownership/race_test.go

📝 Walkthrough

Walkthrough

The filter package adds RejectDuplicateCaseVariantJSONValue and routes byte-based validation through it. Ownership middleware validates the decoded request object instead of parsing the raw body a second time. Tests cover ambiguous, malformed, and non-object bodies. Benchmark and allocation tests measure the mutation path. Race and non-race test constants support conditional allocation checks.

Suggested labels: second-opinion

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/ownership-label-injection-streaming

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot added the second-opinion Summons Greptile as an independent second-opinion reviewer label Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

second-opinion Summons Greptile as an independent second-opinion reviewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants