Avoid request transform context allocation - #3041
Draft
artl93 wants to merge 2 commits into
Draft
Conversation
added 2 commits
July 12, 2026 16:31
Use a synchronous fast path when the request pipeline contains only exact built-in header transforms. Derived, custom, path, query, and asynchronous transforms retain the existing context-based pipeline. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a5fc9838-21b3-4a7a-b73a-c505ecf64ca1
Assert fast-path eligibility and fallback selection, cover allowed-header ordering, original host and route values, and guard built-in fast-path overrides. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: a5fc9838-21b3-4a7a-b73a-c505ecf64ca1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
StructuredTransformer.TransformRequestAsyncallocates aRequestTransformContextfor every structured request-transform pipeline. That general context is necessary when transforms can mutate destination/path/query state, observe cancellation or request bodies, run asynchronously, or generate custom behavior. It is unnecessary when every request transform is an exact built-in header-only transform.The removed object is 72 bytes per eligible request on the measured .NET 9 runtime.
Change
At transformer construction, compute whether all request transforms are exact known built-in header transforms. Eligible pipelines execute the same transform array in the same order through an internal synchronous path using only:
HttpContextHttpRequestMessageheadersCopiedstateExact type checks preserve derived-transform overrides. If any transform is path/query/body/context/custom/async/derived, the entire pipeline uses the existing
RequestTransformContextpath; there is no mixed-mode execution.The eligible boundary covers original host, X-Forwarded For/Host/Proto/Prefix, RFC Forwarded, header remove/value/route-value, and header allow-list transforms. Tests now assert eligibility/fallback selection,
RequestHeadersAllowedordering andHeadersCopiedtransitions, original-host and route-value behavior, derived fallback, and that every allowlisted type overrides the internal fast-path method.BenchmarkDotNet
EgorBot does not support YARP. Its official README describes a service for
dotnet/runtime, and the runtime performance skill lists onlydotnet/runtimeandEgorBot/runtime-utils. A portable BenchmarkDotNet harness is therefore the pending campaign-policy substitute.Exact comparison:
49b23da6d8b0e9df47abf45d7755173f8467094143911dfd95adf7bd45e2d7cbcb768a24c8c14a18Job.ShortRun, MemoryDiagnoser, 3 measured iterations, 3 warmups, one launchAllocation is the primary metric. The two isolated runs are sequential, so timing is retained only as supporting evidence and no latency claim is made.
Representative exact values:
A separate exact-SHA Kestrel campaign ran 96 interleaved parent/final processes across default, mixed path/query, custom async, and body-observing pipelines; H1/H2; 0/50 extra headers; 10,000 requests after 1,000 warmups; concurrency 64. All requests completed successfully. Process-wide allocation/throughput includes client, proxy, backend, and thread-pool noise, so it is realistic functional evidence rather than a precise performance claim.
Evidence manifests:
/Users/artl/.copilot/session-state/294ad512-dbe2-42ad-8a82-c528f296fdb3/files/readiness-bdn-runs(SHA256SUMShash1f18efc3277968b55f6178830a1c6a3d39a5b555c6b03bba2d85325123132150)/Users/artl/.copilot/session-state/294ad512-dbe2-42ad-8a82-c528f296fdb3/files/readiness-e2e(SHA256SUMShash4aebaf19d23a4a843898486a6e2ba500315481b3604931b07d29fb9a2bd467e9)Validation
Risks and limits
AI disclosure
Implementation, tests, benchmark harnesses, evidence analysis, and this PR text were prepared with GitHub Copilot assistance and manually validated.