From 40bacaab92bcbe793cd099761212236eb5c7178a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 00:56:34 +0000 Subject: [PATCH 1/2] perf: use O(1) dictionary lookup in convTypeRef assembly resolution Replace the O(n) Seq.tryFind scan in the bestGuess step of convTypeRef with O(1) dictionary lookups against the existing assembly-name tables (targetAssembliesTable_ for target, sourceAssembliesTable_ for source). The linear scan in the fallback loop is preserved for the rare case where an assembly simple-name is not in the table (e.g. type-forwarding across assembly boundaries). The per-type translation cache (typeTableFwd / typeTableBwd) already means each unique type is resolved at most once, so this change is most beneficial during the initial warm-up of a large type provider that references many distinct types. All 126 tests pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/ProvidedTypes.fs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/ProvidedTypes.fs b/src/ProvidedTypes.fs index f39fa85..ad3d13b 100644 --- a/src/ProvidedTypes.fs +++ b/src/ProvidedTypes.fs @@ -9196,6 +9196,8 @@ namespace ProviderImplementation.ProvidedTypes ) |> ignore sourceAssemblies_ + let getSourceAssembliesTable() = getSourceAssemblies() |> ignore; sourceAssembliesTable_ + /// When translating quotations, Expr.Var's are translated to new variable respecting reference equality. let varTableFwd = Dictionary() let varTableBwd = Dictionary() @@ -9254,10 +9256,22 @@ namespace ProviderImplementation.ProvidedTypes | _ -> let asms = (if toTgt then getTargetAssemblies() else getSourceAssemblies()) let fullName = fixName t.FullName - - let bestGuess = - asms |> Seq.tryFind(fun a -> a.FullName = t.Assembly.FullName) - |> Option.bind(fun a -> tryGetTypeFromAssembly toTgt t.Assembly.FullName fullName a) + let asmSimpleName = t.Assembly.GetName().Name + + // Use the assembly-name dictionary (O(1)) rather than a sequential scan. + // Fall through to None if the assembly isn't in the table, which lets the + // linear fallback below handle cross-assembly type forwarding edge cases. + let bestGuess = + if toTgt then + let table = getTargetAssembliesTable() + match table.TryGetValue(asmSimpleName) with + | true, Choice1Of2 asm -> tryGetTypeFromAssembly toTgt t.Assembly.FullName fullName asm + | _ -> None + else + let table = getSourceAssembliesTable() + match table.TryGetValue(asmSimpleName) with + | true, asm -> tryGetTypeFromAssembly toTgt t.Assembly.FullName fullName asm + | _ -> None match bestGuess with | Some (newT, canSave) -> From cf33637499291685b5feeb4f3b0ab4fa6c34fd79 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Apr 2026 00:56:37 +0000 Subject: [PATCH 2/2] ci: trigger checks