From 1671a30cb6b70110bd9f55c547d140e76dca313a Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Thu, 14 May 2026 20:09:41 +0000
Subject: [PATCH 1/2] perf: add string/int fast-paths in toParam; use
StringBuilder+String.Concat in buildXmlDoc
- toParam: add explicit match arms for string, int32, int64, bool to skip
GetType() + four type checks (two FullName comparisons, IsGenericType, IsEnum)
for the most common OpenAPI scalar parameter types.
- buildXmlDoc (Utils.fs): replace list-comprehension + String.concat for
paramParts with a StringBuilder loop to avoid F# list cons-cell allocation;
replace the final four-way string concatenation with String.Concat(a,b,c,d)
to avoid two intermediate string allocations per compiled operation.
All 417 unit tests pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
src/SwaggerProvider.DesignTime/Utils.fs | 16 +++++++++++-----
src/SwaggerProvider.Runtime/RuntimeHelpers.fs | 7 +++++++
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/SwaggerProvider.DesignTime/Utils.fs b/src/SwaggerProvider.DesignTime/Utils.fs
index ac5f7d6b..49d9ad64 100644
--- a/src/SwaggerProvider.DesignTime/Utils.fs
+++ b/src/SwaggerProvider.DesignTime/Utils.fs
@@ -372,17 +372,23 @@ module XmlDoc =
$"{escapeXml description}"
let paramParts =
- [ for name, desc in paramDescriptions do
- if not(String.IsNullOrWhiteSpace desc) then
- yield $"{escapeXml desc}" ]
- |> String.concat ""
+ let sb = System.Text.StringBuilder()
+
+ for name, desc in paramDescriptions do
+ if not(String.IsNullOrWhiteSpace desc) then
+ sb.Append("").Append(escapeXml desc).Append("")
+ |> ignore
+
+ sb.ToString()
let returnsPart =
match returnDoc with
| Some rd when not(String.IsNullOrWhiteSpace rd) -> $"{escapeXml rd}"
| _ -> ""
- summaryPart + remarksPart + paramParts + returnsPart
+ // Use String.Concat with 4 arguments instead of chained + operators to avoid
+ // two intermediate string allocations (one per + in `a + b + c + d`).
+ String.Concat(summaryPart, remarksPart, paramParts, returnsPart)
type UniqueNameGenerator(?occupiedNames: string seq) =
let hash = System.Collections.Generic.HashSet<_>()
diff --git a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs
index 504c38f3..dbc2df3a 100644
--- a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs
+++ b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs
@@ -211,6 +211,13 @@ module RuntimeHelpers =
| :? DateTime as dt -> dt.ToString("O")
| :? DateTimeOffset as dto -> dto.ToString("O")
| null -> null
+ // Fast paths for the most common scalar param types:
+ // these avoid calling GetType() and the four subsequent type checks
+ // (FullName twice, IsGenericType, IsEnum) that follow in the generic branch.
+ | :? string as s -> s
+ | :? int32 as i -> i.ToString()
+ | :? int64 as i -> i.ToString()
+ | :? bool as b -> b.ToString()
| _ ->
// Hoist GetType() once; previously tryFormatDateOnly and tryFormatTimeOnly
// each called GetType() internally, resulting in up to 3 GetType() calls for
From 9a4e5a6d1ba68e262b720b5bdb9a56ad275b9932 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Thu, 14 May 2026 20:09:44 +0000
Subject: [PATCH 2/2] ci: trigger checks