[Repo Assist] perf: eliminate redundant GetType() calls in toParam#410
Merged
sergey-tihon merged 3 commits intomasterfrom Apr 28, 2026
Conversation
Previously, toParam dispatched through tryFormatDateOnly and tryFormatTimeOnly, each of which called value.GetType() internally. For any non-DateTime/non-DateTimeOffset scalar type (string, int, Guid, bool, etc.), this resulted in up to 3 GetType() calls before falling through to obj.ToString(). Restructure toParam to call GetType() once at the top of the catch-all branch, then dispatch to a shared formatDateOrTimeValue helper or the option unwrapping path as needed. The three private helpers (tryFormatViaMethods, tryFormatDateOnly, tryFormatTimeOnly) are removed; formatDateOrTimeValue replaces them with an API that accepts the pre-computed Type, making the single GetType() call obvious at the call site. Behavior is identical; all 327 unit tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR optimizes RuntimeHelpers.toParam in the runtime library by reducing redundant reflection work when serializing parameters (query/form/header/multipart), keeping DateOnly/TimeOnly formatting and F# option unwrapping behavior intact.
Changes:
- Hoists
GetType()once intoParam’s fallback path and dispatches viaif/elif. - Replaces
tryFormatDateOnly/tryFormatTimeOnly(and their shared helper) with a singleformatDateOrTimeValuehelper that accepts a precomputedType. - Removes the now-dead private formatting helpers.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI
added a commit
that referenced
this pull request
Apr 28, 2026
Master (#410) restructured toParam to call GetType() once at the top, while the enum branch (this PR) added an 'elif ty.IsEnum' arm after the Option<T> check. The two changes are compatible: keep the single-GetType() structure from master and preserve the enum serializer dispatch from this PR. Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com>
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.
🤖 This PR was created by Repo Assist, an automated AI assistant.
Summary
toParaminRuntimeHelpers.fspreviously dispatched through two private helpers (tryFormatDateOnly,tryFormatTimeOnly) that each calledvalue.GetType()internally. For any common scalar type (string, int, Guid, bool, etc.) this caused up to 3GetType()calls per invocation — one insidetryFormatDateOnly, one insidetryFormatTimeOnly, and a third in the option-unwrapping branch — before finally reachingobj.ToString().Change
GetType()once at the top of the catch-all branch intoParam, then dispatch usingif/elifchains.tryFormatViaMethods,tryFormatDateOnly,tryFormatTimeOnly).formatDateOrTimeValue— a focused helper that accepts the pre-computedType, making the single-call contract explicit at the call site.obj.ToString()) is identical.Impact
toParamis called for every HTTP parameter — query strings, form fields, headers, multipart parts. For a typical form-encoded API call with 10–20 fields, this eliminates ~20–40 redundantGetType()calls. While eachGetType()is fast, the savings are meaningful for high-throughput or batch-heavy callers (e.g. issue #150, the Stripe 3 MB schema hang, where parameter serialization is on the hot path).Trade-offs
None. The fallback
GetMethod("ToString", ...)path informatDateOrTimeValueis preserved for forward-compatibility, even thoughDateOnlyandTimeOnlyboth implementIFormattableon all .NET versions where they exist.Test Status
✅ Build:
dotnet build tests/SwaggerProvider.Tests/SwaggerProvider.Tests.fsproj -c Release— 0 errors, 0 failures✅ Tests: 327 total, 0 failed, 1 skipped (pre-existing skip)
✅ Format:
dotnet fantomas --checkpassed after formatting