From 8b0f605986a8c3bd3c54717622da2271f4e889af Mon Sep 17 00:00:00 2001 From: dotnetjunkie Date: Wed, 28 Sep 2022 22:17:14 +0200 Subject: [PATCH] Optimization. Saved 8 bytes of memory per InstanceProducer. #956 --- src/SimpleInjector/InstanceProducer.cs | 4 ++-- .../Internals/CyclicDependencyValidator.cs | 17 ++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/SimpleInjector/InstanceProducer.cs b/src/SimpleInjector/InstanceProducer.cs index 957537bb..78667ef3 100644 --- a/src/SimpleInjector/InstanceProducer.cs +++ b/src/SimpleInjector/InstanceProducer.cs @@ -107,7 +107,7 @@ internal InstanceProducer(Type serviceType, Registration registration, bool regi this.ServiceType = serviceType; this.Registration = registration; - this.validator = new CyclicDependencyValidator(this); + this.validator = new CyclicDependencyValidator(); this.lazyExpression = new LazyEx(this.BuildExpressionInternal); @@ -658,7 +658,7 @@ private object BuildAndReplaceInstanceCreatorAndCreateFirstInstance() [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] private void CheckForCyclicDependencies() { - this.validator?.Check(); + this.validator?.Check(this); } // This method will be inlined by the JIT. diff --git a/src/SimpleInjector/Internals/CyclicDependencyValidator.cs b/src/SimpleInjector/Internals/CyclicDependencyValidator.cs index 7897fe26..cbf98cee 100644 --- a/src/SimpleInjector/Internals/CyclicDependencyValidator.cs +++ b/src/SimpleInjector/Internals/CyclicDependencyValidator.cs @@ -21,8 +21,6 @@ namespace SimpleInjector.Internals /// internal sealed class CyclicDependencyValidator { - private readonly InstanceProducer producer; - // If needed, we can do an extra optimization, which is to have an extra int field for the first // entered thread. This prevents the list from having to be newed in most cases, as typically there // is only on thread entering at the same time. This does complicate the code of this class though. @@ -31,20 +29,21 @@ internal sealed class CyclicDependencyValidator // path, however, is somethings we prevent at all costs. private List? enteredThreads; - internal CyclicDependencyValidator(InstanceProducer producer) - { - this.producer = producer; - } - // Checks whether this is a recursive call (and thus a cyclic dependency) and throw in that case. - internal void Check() + // MEMORY: By passing the instance producer in through this method instead of through the ctor, + // this class becomes 8 bytes smaller (on 64 bits) and results in less memory used. This is + // important, because every InstanceProducer gets its own validator and 95% of all validators + // stay in memory. + // TODO: We can reduce an extra 8 bytes of memory per InstanceProducer by merging this class into + // the InstanceProducer itself. + internal void Check(InstanceProducer producer) { lock (this) { if (this.IsCurrentThreadReentering()) { throw new CyclicDependencyException( - this.producer, this.producer.Registration.ImplementationType); + producer, producer.Registration.ImplementationType); } this.MarkCurrentThreadAsEntering();