From fe2e4a7b37ff9dad1037c7e36f9ebc0fe6aa3925 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 13:26:14 +0000 Subject: [PATCH 1/3] perf: cache DateOnly/TimeOnly type lookups in DefinitionCompiler System.Type.GetType() scans all loaded assemblies on every call. Previously it was invoked once per 'date' or 'time' format field encountered during schema compilation. For a large schema with many date/time properties, this added measurable design-time overhead. Resolve both types once at DefinitionCompiler construction into dateOnlyTy and timeOnlyTy private let bindings. The match expressions in compileBySchema now reference these cached values directly, reducing design-time schema compilation cost. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DefinitionCompiler.fs | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs b/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs index dff29207..1ca98de0 100644 --- a/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs +++ b/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs @@ -185,6 +185,26 @@ type DefinitionCompiler(schema: OpenApiDocument, provideNullable, useDateOnly: b // when compiling large schemas with many object types. let objToStringMethod = typeof.GetMethod("ToString", [||]) + // Resolve DateOnly/TimeOnly once per compiler instance rather than on every + // date/time property. System.Type.GetType scans all loaded assemblies on each + // call, so repeating it for every field in a large schema adds measurable + // design-time overhead. + let dateOnlyTy = + if useDateOnly then + System.Type.GetType("System.DateOnly") + |> Option.ofObj + |> Option.defaultValue typeof + else + typeof + + let timeOnlyTy = + if useDateOnly then + System.Type.GetType("System.TimeOnly") + |> Option.ofObj + |> Option.defaultValue typeof + else + typeof + let generateProperty (scope: UniqueNameGenerator) propName ty = let propertyName = scope.MakeUnique <| nicePascalName propName @@ -628,25 +648,13 @@ type DefinitionCompiler(schema: OpenApiDocument, provideNullable, useDateOnly: b // for `multipart/form-data` : https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#considerations-for-file-uploads typeof | HasFlag JsonSchemaType.String, "date" -> - // Use DateOnly only when the target runtime supports it (.NET 6+). - // We check useDateOnly (derived from cfg.SystemRuntimeAssemblyVersion) rather than - // probing the design-time host process, which may differ from the consumer's runtime. - if useDateOnly then - System.Type.GetType("System.DateOnly") - |> Option.ofObj - |> Option.defaultValue typeof - else - typeof + // Resolved once at class construction to dateOnlyTy; avoids a + // System.Type.GetType() call per field in large schemas. + dateOnlyTy | HasFlag JsonSchemaType.String, "date-time" -> typeof | HasFlag JsonSchemaType.String, "time" -> - // Use TimeOnly only when the target runtime supports it (.NET 6+). - // useDateOnly is true for net6+ targets — TimeOnly was added in the same release. - if useDateOnly then - System.Type.GetType("System.TimeOnly") - |> Option.ofObj - |> Option.defaultValue typeof - else - typeof + // Resolved once at class construction to timeOnlyTy. + timeOnlyTy | HasFlag JsonSchemaType.String, "uuid" -> typeof | HasFlag JsonSchemaType.String, _ -> typeof | HasFlag JsonSchemaType.Array, _ -> From 05e84044b56ed33274f4006bd4ee4303ac5d2af1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 29 Apr 2026 13:26:17 +0000 Subject: [PATCH 2/3] ci: trigger checks From 50f00fccc4c6cbaeed034cc9b6bc80bb1acdb952 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Apr 2026 19:50:43 +0000 Subject: [PATCH 3/3] perf: use lazy dateOnlyTy/timeOnlyTy and fix misleading comment Agent-Logs-Url: https://github.com/fsprojects/SwaggerProvider/sessions/fd4d1ca3-3705-428b-895d-7e1902cc9ae2 Co-authored-by: sergey-tihon <1197905+sergey-tihon@users.noreply.github.com> --- .../DefinitionCompiler.fs | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs b/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs index 1ca98de0..c504f490 100644 --- a/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs +++ b/src/SwaggerProvider.DesignTime/DefinitionCompiler.fs @@ -185,25 +185,26 @@ type DefinitionCompiler(schema: OpenApiDocument, provideNullable, useDateOnly: b // when compiling large schemas with many object types. let objToStringMethod = typeof.GetMethod("ToString", [||]) - // Resolve DateOnly/TimeOnly once per compiler instance rather than on every - // date/time property. System.Type.GetType scans all loaded assemblies on each - // call, so repeating it for every field in a large schema adds measurable - // design-time overhead. + // Resolve DateOnly/TimeOnly lazily and cache the result per compiler instance. + // This preserves the "only pay when needed" behavior while still avoiding + // repeated reflection lookups for schemas that actually use date/time formats. let dateOnlyTy = - if useDateOnly then - System.Type.GetType("System.DateOnly") - |> Option.ofObj - |> Option.defaultValue typeof - else - typeof + lazy + (if useDateOnly then + System.Type.GetType("System.DateOnly") + |> Option.ofObj + |> Option.defaultValue typeof + else + typeof) let timeOnlyTy = - if useDateOnly then - System.Type.GetType("System.TimeOnly") - |> Option.ofObj - |> Option.defaultValue typeof - else - typeof + lazy + (if useDateOnly then + System.Type.GetType("System.TimeOnly") + |> Option.ofObj + |> Option.defaultValue typeof + else + typeof) let generateProperty (scope: UniqueNameGenerator) propName ty = let propertyName = scope.MakeUnique <| nicePascalName propName @@ -647,14 +648,9 @@ type DefinitionCompiler(schema: OpenApiDocument, provideNullable, useDateOnly: b // for `application/octet-stream` request body // for `multipart/form-data` : https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#considerations-for-file-uploads typeof - | HasFlag JsonSchemaType.String, "date" -> - // Resolved once at class construction to dateOnlyTy; avoids a - // System.Type.GetType() call per field in large schemas. - dateOnlyTy + | HasFlag JsonSchemaType.String, "date" -> dateOnlyTy.Value | HasFlag JsonSchemaType.String, "date-time" -> typeof - | HasFlag JsonSchemaType.String, "time" -> - // Resolved once at class construction to timeOnlyTy. - timeOnlyTy + | HasFlag JsonSchemaType.String, "time" -> timeOnlyTy.Value | HasFlag JsonSchemaType.String, "uuid" -> typeof | HasFlag JsonSchemaType.String, _ -> typeof | HasFlag JsonSchemaType.Array, _ ->