Pipeline optimization
This commit is contained in:
Родитель
9e6bf0fc4a
Коммит
7cd989876b
|
@ -136,7 +136,7 @@ namespace Unity
|
|||
keyDefault = new HashKey(generic);
|
||||
}
|
||||
|
||||
// Factory with the same name
|
||||
// Generic Factory
|
||||
targetBucket = keyGeneric.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
|
@ -144,11 +144,11 @@ namespace Unity
|
|||
if (candidate.Key != keyGeneric)
|
||||
continue;
|
||||
|
||||
// Found a factory
|
||||
// Found a generic factory
|
||||
return container.PipelineFromOpenGeneric(ref key, candidate.Registration);
|
||||
}
|
||||
|
||||
// Default factory
|
||||
// Default Factory
|
||||
targetBucket = keyDefault.HashCode % registry.Buckets.Length;
|
||||
for (var i = registry.Buckets[targetBucket]; i >= 0; i = registry.Entries[i].Next)
|
||||
{
|
||||
|
@ -156,9 +156,8 @@ namespace Unity
|
|||
if (candidate.Key != keyDefault)
|
||||
continue;
|
||||
|
||||
// Found a factory
|
||||
var typeFactory = (TypeFactoryDelegate)candidate.Policies.Get(typeof(TypeFactoryDelegate));
|
||||
return container.PipelineFromTypeFactory(ref key, container, typeFactory);
|
||||
// Found a default
|
||||
return container.PipelineFromTypeFactory(ref key, container, candidate.Policies);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Registration;
|
||||
|
@ -18,10 +19,12 @@ namespace Unity
|
|||
var type = key.Type;
|
||||
var name = key.Name;
|
||||
var owner = this;
|
||||
bool AddNew = true;
|
||||
bool adding = true;
|
||||
int position = 0;
|
||||
var collisions = 0;
|
||||
|
||||
LifetimeManager? manager = null;
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
// Add Pipeline to the Registry
|
||||
lock (_syncRegistry)
|
||||
|
@ -39,17 +42,18 @@ namespace Unity
|
|||
// Pipeline already been created
|
||||
if (null != candidate.Pipeline) return candidate.Pipeline;
|
||||
|
||||
// Empty Registration with Policies
|
||||
// Lifetime Manager
|
||||
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
// Type has not been registered
|
||||
if (null == candidate.Registration) candidate.Pipeline = manager.Pipeline;
|
||||
|
||||
AddNew = false;
|
||||
adding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (AddNew)
|
||||
if (adding)
|
||||
{
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
|
@ -58,8 +62,9 @@ namespace Unity
|
|||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Create a Lifetime Manager
|
||||
// Lifetime Manager
|
||||
manager = factory.LifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
// Create new entry
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
|
@ -75,10 +80,32 @@ namespace Unity
|
|||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, factory, manager, this);
|
||||
manager.PipelineDelegate = builder.Pipeline();
|
||||
lock (manager)
|
||||
{
|
||||
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, factory, manager, this);
|
||||
manager.PipelineDelegate = builder.Pipeline();
|
||||
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
return manager.Pipeline;
|
||||
|
||||
|
||||
object? SpinWait(ref BuilderContext context)
|
||||
{
|
||||
while (null == pipeline)
|
||||
{
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
for (var i = 0; i < 100; i++) ;
|
||||
#else
|
||||
Thread.SpinWait(100);
|
||||
#endif
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Registration;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
@ -17,19 +17,46 @@ namespace Unity
|
|||
|
||||
var manager = registration.LifetimeManager;
|
||||
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
|
||||
|
||||
lock (_syncRegistry)
|
||||
{
|
||||
ref var entry = ref _registry.Entries[position];
|
||||
if (ReferenceEquals(entry.Registration, registration)) entry.Pipeline = manager.Pipeline;
|
||||
|
||||
if (ReferenceEquals(entry.Registration, registration) && null == entry.Pipeline)
|
||||
{
|
||||
entry.Pipeline = manager.Pipeline;
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
}
|
||||
}
|
||||
|
||||
if (null == manager.PipelineDelegate)
|
||||
lock (manager)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, registration);
|
||||
manager.PipelineDelegate = builder.Pipeline();
|
||||
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, registration);
|
||||
manager.PipelineDelegate = builder.Pipeline();
|
||||
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
return manager.Pipeline;
|
||||
|
||||
|
||||
object? SpinWait(ref BuilderContext context)
|
||||
{
|
||||
while (null == pipeline)
|
||||
{
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
for (var i = 0; i < 100; i++) ;
|
||||
#else
|
||||
Thread.SpinWait(100);
|
||||
#endif
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using Unity.Builder;
|
||||
using Unity.Lifetime;
|
||||
using Unity.Policy;
|
||||
using Unity.Resolution;
|
||||
using Unity.Storage;
|
||||
|
||||
|
@ -8,7 +11,7 @@ namespace Unity
|
|||
{
|
||||
public partial class UnityContainer
|
||||
{
|
||||
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, TypeFactoryDelegate typeFactory)
|
||||
private ResolveDelegate<BuilderContext> PipelineFromTypeFactory(ref HashKey key, UnityContainer container, IPolicySet set)
|
||||
{
|
||||
Debug.Assert(null != _registry);
|
||||
Debug.Assert(null != key.Type);
|
||||
|
@ -17,10 +20,14 @@ namespace Unity
|
|||
var name = key.Name;
|
||||
var owner = this;
|
||||
|
||||
int count = -1;
|
||||
int position = 0;
|
||||
var collisions = 0;
|
||||
|
||||
|
||||
bool adding = true;
|
||||
LifetimeManager? manager = null;
|
||||
ResolveDelegate<BuilderContext>? pipeline = null;
|
||||
var typeFactory = (TypeFactoryDelegate)set.Get(typeof(TypeFactoryDelegate));
|
||||
|
||||
// Add Pipeline to the Registry
|
||||
lock (_syncRegistry)
|
||||
|
@ -35,39 +42,64 @@ namespace Unity
|
|||
continue;
|
||||
}
|
||||
|
||||
Debug.Assert(null != candidate.Pipeline);
|
||||
// Pipeline already been created
|
||||
if (null != candidate.Pipeline) return candidate.Pipeline;
|
||||
|
||||
// Has already been created
|
||||
return candidate.Pipeline;
|
||||
// Lifetime Manager
|
||||
manager = (LifetimeManager)set.Get(typeof(LifetimeManager)) ??
|
||||
Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
// Type has not been registered
|
||||
if (null == candidate.Registration) candidate.Pipeline = manager.Pipeline;
|
||||
|
||||
adding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
if (adding)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
{
|
||||
_registry = new Registry(_registry);
|
||||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Create new entry
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Pipeline = BuildPipeline;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
// Lifetime Manager
|
||||
manager = (LifetimeManager)set.Get(typeof(LifetimeManager)) ??
|
||||
Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
// Create new entry
|
||||
ref var entry = ref _registry.Entries[_registry.Count];
|
||||
entry.Key = key;
|
||||
entry.Pipeline = manager.Pipeline;
|
||||
entry.Next = _registry.Buckets[targetBucket];
|
||||
position = _registry.Count++;
|
||||
_registry.Buckets[targetBucket] = position;
|
||||
}
|
||||
}
|
||||
|
||||
// Return temporary pipeline
|
||||
return BuildPipeline;
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
|
||||
// Create pipeline and add to Registry
|
||||
object? BuildPipeline(ref BuilderContext context)
|
||||
lock (manager)
|
||||
{
|
||||
// Wait for right moment
|
||||
while (0 != Interlocked.Increment(ref count))
|
||||
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
|
||||
{
|
||||
manager.PipelineDelegate = typeFactory(type, this);
|
||||
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
return manager.Pipeline;
|
||||
|
||||
|
||||
|
||||
object? SpinWait(ref BuilderContext context)
|
||||
{
|
||||
while (null == pipeline)
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
#if NETSTANDARD1_0 || NETCOREAPP1_0
|
||||
for (var i = 0; i < 100; i++) ;
|
||||
#else
|
||||
|
@ -75,22 +107,8 @@ namespace Unity
|
|||
#endif
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Create if required
|
||||
if (null == pipeline)
|
||||
{
|
||||
pipeline = typeFactory(type, container);
|
||||
Debug.Assert(null != pipeline);
|
||||
}
|
||||
|
||||
return pipeline(ref context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref count);
|
||||
}
|
||||
};
|
||||
return pipeline(ref context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace Unity
|
|||
|
||||
lock (_syncRegistry)
|
||||
{
|
||||
var AddNew = true;
|
||||
var adding = true;
|
||||
var collisions = 0;
|
||||
var targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
for (var i = _registry.Buckets[targetBucket]; i >= 0; i = _registry.Entries[i].Next)
|
||||
|
@ -35,7 +35,7 @@ namespace Unity
|
|||
// Pipeline already been created
|
||||
if (null != existing.Pipeline) return existing.Pipeline;
|
||||
|
||||
// Empty Registration with Policies
|
||||
// Lifetime Manager
|
||||
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
|
@ -43,11 +43,11 @@ namespace Unity
|
|||
if (null == existing.Registration) existing.Pipeline = manager.Pipeline;
|
||||
|
||||
// Skip to creation part
|
||||
AddNew = false;
|
||||
adding = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (AddNew)
|
||||
if (adding)
|
||||
{
|
||||
// Expand if required
|
||||
if (_registry.RequireToGrow || CollisionsCutPoint < collisions)
|
||||
|
@ -56,6 +56,7 @@ namespace Unity
|
|||
targetBucket = key.HashCode % _registry.Buckets.Length;
|
||||
}
|
||||
|
||||
// Lifetime Manager
|
||||
manager = Context.TypeLifetimeManager.CreateLifetimePolicy();
|
||||
manager.PipelineDelegate = (ResolveDelegate<BuilderContext>)SpinWait;
|
||||
|
||||
|
@ -72,14 +73,18 @@ namespace Unity
|
|||
|
||||
Debug.Assert(null != manager);
|
||||
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, this, Context.TypePipelineCache);
|
||||
lock (manager)
|
||||
{
|
||||
if ((Delegate)(ResolveDelegate<BuilderContext>)SpinWait == manager.PipelineDelegate)
|
||||
{
|
||||
PipelineBuilder builder = new PipelineBuilder(key.Type, this, Context.TypePipelineCache);
|
||||
manager.PipelineDelegate = builder.Pipeline();
|
||||
pipeline = (ResolveDelegate<BuilderContext>)manager.PipelineDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
var newPipeline = builder.Pipeline();
|
||||
return manager.Pipeline;
|
||||
|
||||
manager.PipelineDelegate = newPipeline;
|
||||
pipeline = newPipeline;
|
||||
|
||||
return pipeline;
|
||||
|
||||
object? SpinWait(ref BuilderContext context)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче