Skip to content

Commit

Permalink
Optimization. Saved 8 bytes of memory per InstanceProducer. #956
Browse files Browse the repository at this point in the history
  • Loading branch information
dotnetjunkie committed Sep 28, 2022
1 parent 48ef4b2 commit 8b0f605
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/SimpleInjector/InstanceProducer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Expression>(this.BuildExpressionInternal);

Expand Down Expand Up @@ -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.
Expand Down
17 changes: 8 additions & 9 deletions src/SimpleInjector/Internals/CyclicDependencyValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ namespace SimpleInjector.Internals
/// </remarks>
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.
Expand All @@ -31,20 +29,21 @@ internal sealed class CyclicDependencyValidator
// path, however, is somethings we prevent at all costs.
private List<int>? 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();
Expand Down

0 comments on commit 8b0f605

Please sign in to comment.