diff --git a/Directory.Packages.props b/Directory.Packages.props index c3fc950111..3af4eabf2a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,7 +14,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Marten/Events/EventGraph.cs b/src/Marten/Events/EventGraph.cs index 42a08ab47a..a1e2c28573 100644 --- a/src/Marten/Events/EventGraph.cs +++ b/src/Marten/Events/EventGraph.cs @@ -606,10 +606,31 @@ internal void Initialize(DocumentStore store) _tombstones = new RetryBlock(executeTombstoneBlock, logger, _cancellation.Token); - foreach (var mapping in _events) + + // Pre-warm name->type so the first read of each event type from the database + // doesn't fall through Type.GetType(assemblyQualifiedName) in TypeForDotNetName, + // which is itself O(loaded-assemblies). Populate both AssemblyQualifiedName and + // FullName since both shapes appear in event metadata over the lifetime of a + // store. Done as a single Swap so we don't churn ImHashMap. + _nameToType.Swap(map => { - mapping.JsonTransformation(null); - } + foreach (var mapping in _events) + { + mapping.JsonTransformation(null); + + var docType = mapping.DocumentType; + if (docType.AssemblyQualifiedName is { } aqn) + { + map = map.AddOrUpdate(aqn, docType); + } + if (docType.FullName is { } fullName) + { + map = map.AddOrUpdate(fullName, docType); + } + } + + return map; + }); autoDiscoverTagTypesFromProjections(); }