Skip to content

Commit 4fac580

Browse files
author
maximv
committed
small perf optimizations with adding TrackDisposableWithoutDisposalOrder
1 parent 35c06f6 commit 4fac580

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

src/DryIoc/Container.cs

+42-20
Original file line numberDiff line numberDiff line change
@@ -3321,7 +3321,7 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
33213321
{
33223322
if (!TryInterpret(resolver, callArgs[2], paramExprs, paramValues, parentArgs, useFec, out var service))
33233323
return false;
3324-
result = scope.TrackDisposable(service); // todo: what is with `disposalOrder`
3324+
result = service is IDisposable d ? scope.TrackDisposableWithoutDisposalOrder(d) : service;
33253325
}
33263326

33273327
return true;
@@ -3336,7 +3336,7 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
33363336
{
33373337
if (!TryInterpret(resolver, callArgs[3], paramExprs, paramValues, parentArgs, useFec, out var service))
33383338
return false;
3339-
result = scope.TrackDisposable(service);
3339+
result = service is IDisposable d ? scope.TrackDisposableWithoutDisposalOrder(d) : service;
33403340
}
33413341

33423342
return true;
@@ -3359,9 +3359,9 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
33593359
{
33603360
if (TryInterpret(rc, e, paramExprs, paramValues, parentArgs, uf, out var value))
33613361
return value;
3362-
return e.CompileToFactoryDelegate(uf, ((IContainer) rc).Rules.UseInterpretation)(rc);
3362+
return e.CompileToFactoryDelegate(uf, ((IContainer)rc).Rules.UseInterpretation)(rc);
33633363
},
3364-
(int) ConstValue(callArgs[3]));
3364+
(int)ConstValue(callArgs[3]));
33653365
}
33663366

33673367
return true;
@@ -3372,7 +3372,14 @@ private static bool TryInterpretMethodCall(IResolverContext r, Expression expr,
33723372
r = r.Root ?? r;
33733373
if (!TryInterpret(r, callArgs[0], paramExprs, paramValues, parentArgs, useFec, out var service))
33743374
return false;
3375-
result = r.SingletonScope.TrackDisposable(service, (int)ConstValue(callArgs[1]));
3375+
if (service is IDisposable d)
3376+
{
3377+
var disposalOrder = (int)ConstValue(callArgs[1]);
3378+
result = disposalOrder == 0
3379+
? r.SingletonScope.TrackDisposableWithoutDisposalOrder(d)
3380+
: r.SingletonScope.TrackDisposable(service, disposalOrder);
3381+
}
3382+
33763383
return true;
33773384
}
33783385
}
@@ -4713,7 +4720,7 @@ public static IResolverContext OpenScope(this IResolverContext r, object name =
47134720
var parentScope = r.CurrentScope;
47144721
var newOwnScope = new Scope(parentScope, name);
47154722
if (trackInParent)
4716-
(parentScope ?? r.SingletonScope).TrackDisposable(newOwnScope);
4723+
(parentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder(newOwnScope);
47174724
return r.WithCurrentScope(newOwnScope);
47184725
}
47194726

@@ -4722,7 +4729,7 @@ public static IResolverContext OpenScope(this IResolverContext r, object name =
47224729
: r.ScopeContext.SetCurrent(parent => new Scope(parent, name));
47234730

47244731
if (trackInParent)
4725-
(newContextScope.Parent ?? r.SingletonScope).TrackDisposable(newContextScope);
4732+
(newContextScope.Parent ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder(newContextScope);
47264733
return r.WithCurrentScope(null);
47274734
}
47284735

@@ -4737,7 +4744,7 @@ internal static bool TryGetUsedInstance(this IResolverContext r, Type serviceTyp
47374744
// todo: @perf no need to check for IDisposable in TrackDisposable
47384745
/// <summary>A bit if sugar to track disposable in the current scope or in the singleton scope as a fallback</summary>
47394746
public static T TrackDisposable<T>(this IResolverContext r, T instance) where T : IDisposable =>
4740-
(T)(r.CurrentScope ?? r.SingletonScope).TrackDisposable(instance);
4747+
(T)(r.CurrentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder(instance);
47414748
}
47424749

47434750
/// <summary>The result delegate generated by DryIoc for service creation.</summary>
@@ -6891,8 +6898,8 @@ public static void RegisterInstance(this IRegistrator registrator, bool isChecke
68916898
serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: false);
68926899

68936900
// done after registration to pass all the registration validation checks
6894-
if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6895-
(registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance);
6901+
if (instance is IDisposable d && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6902+
(registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d);
68966903
}
68976904

68986905
/// <summary>
@@ -6945,8 +6952,9 @@ public static void RegisterInstanceMany(this IRegistrator registrator, Type impl
69456952
foreach (var serviceType in serviceTypes)
69466953
registrator.Register(factory, serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: true);
69476954

6948-
if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6949-
(registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance);
6955+
if (instance is IDisposable d &&
6956+
(setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6957+
(registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d);
69506958
}
69516959

69526960
/// <summary>
@@ -6986,8 +6994,9 @@ public static void RegisterInstanceMany(this IRegistrator registrator, Type[] se
69866994
registrator.Register(factory, serviceType, serviceKey, ifAlreadyRegistered, isStaticallyChecked: true);
69876995
}
69886996

6989-
if (instance is IDisposable && (setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6990-
(registrator as IResolverContext)?.SingletonScope.TrackDisposable(instance);
6997+
if (instance is IDisposable d &&
6998+
(setup == null || (!setup.PreventDisposal && !setup.WeaklyReferenced)))
6999+
(registrator as IResolverContext)?.SingletonScope.TrackDisposableWithoutDisposalOrder(d);
69917000
}
69927001

69937002
/// <summary>List of types excluded by default from RegisterMany convention.</summary>
@@ -11339,11 +11348,13 @@ object TryGetOrAddWithoutClosure(int id,
1133911348
IResolverContext resolveContext, Expression expr, bool useFec,
1134011349
Func<IResolverContext, Expression, bool, object> createValue, int disposalOrder = 0);
1134111350

11342-
// todo: @perf introduce the overload WithoutDisposalOrder
1134311351
/// <summary>Tracked item will be disposed with the scope.
1134411352
/// Smaller <paramref name="disposalOrder"/> will be disposed first.</summary>
1134511353
object TrackDisposable(object item, int disposalOrder = 0);
1134611354

11355+
/// <summary>Tracked item will be disposed with the scope.</summary>
11356+
T TrackDisposableWithoutDisposalOrder<T>(T disposable) where T : IDisposable;
11357+
1134711358
///<summary>Sets or adds the service item directly to the scope services</summary>
1134811359
void SetOrAdd(int id, object item);
1134911360

@@ -11683,7 +11694,7 @@ public bool TryGet(out object item, int id)
1168311694
/// <summary>Can be used to manually add service for disposal</summary>
1168411695
public object TrackDisposable(object item, int disposalOrder = 0)
1168511696
{
11686-
if (item is IDisposable disposable && disposable != this)
11697+
if (item is IDisposable disposable && !ReferenceEquals(disposable, this))
1168711698
if (disposalOrder == 0)
1168811699
AddUnorderedDisposable(disposable);
1168911700
else
@@ -11694,6 +11705,18 @@ public object TrackDisposable(object item, int disposalOrder = 0)
1169411705
internal static readonly MethodInfo TrackDisposableMethod =
1169511706
typeof(IScope).GetTypeInfo().GetDeclaredMethod(nameof(IScope.TrackDisposable));
1169611707

11708+
/// <summary>Tracked item will be disposed with the scope.</summary>
11709+
public T TrackDisposableWithoutDisposalOrder<T>(T disposable) where T : IDisposable
11710+
{
11711+
if (!ReferenceEquals(disposable, this))
11712+
{
11713+
var copy = _unorderedDisposables;
11714+
if (Interlocked.CompareExchange(ref _unorderedDisposables, copy.Push(disposable), copy) != copy)
11715+
Ref.Swap(ref _unorderedDisposables, disposable, (x, d) => x.Push(d));
11716+
}
11717+
return disposable;
11718+
}
11719+
1169711720
///[Obsolete("Removing because it is not used")]
1169811721
public void SetUsedInstance(Type type, FactoryDelegate factory) =>
1169911722
SetUsedInstance(RuntimeHelpers.GetHashCode(type), type, factory);
@@ -11984,7 +12007,6 @@ public Expression Apply(Request request, Expression serviceFactoryExpr)
1198412007
serviceFactoryExpr = Convert(serviceFactoryExpr, typeof(object));
1198512008

1198612009
var resolverContextParamExpr = FactoryDelegateCompiler.ResolverContextParamExpr;
11987-
1198812010
if (request.TracksTransientDisposable)
1198912011
{
1199012012
if (ScopedOrSingleton)
@@ -12102,7 +12124,7 @@ public static object GetScopedOrSingletonViaFactoryDelegate(IResolverContext r,
1210212124
/// <summary>Tracks the Unordered disposal in the current scope or in the singleton as fallback</summary>
1210312125
[MethodImpl((MethodImplOptions)256)]
1210412126
public static object TrackScopedOrSingleton(IResolverContext r, object item) =>
12105-
(r.CurrentScope ?? r.SingletonScope).TrackDisposable(item);
12127+
item is IDisposable d ? (r.CurrentScope ?? r.SingletonScope).TrackDisposableWithoutDisposalOrder(d) : item;
1210612128

1210712129
internal static readonly MethodInfo TrackScopedOrSingletonMethod =
1210812130
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackScopedOrSingleton));
@@ -12143,14 +12165,14 @@ public static object GetNameScopedViaFactoryDelegate(IResolverContext r,
1214312165

1214412166
/// Subject
1214512167
public static object TrackScoped(IResolverContext r, bool throwIfNoScope, object item) =>
12146-
r.GetCurrentScope(throwIfNoScope)?.TrackDisposable(item);
12168+
item is IDisposable d ? r.GetCurrentScope(throwIfNoScope)?.TrackDisposableWithoutDisposalOrder(d) : item;
1214712169

1214812170
internal static readonly MethodInfo TrackScopedMethod =
1214912171
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackScoped));
1215012172

1215112173
/// Subject
1215212174
public static object TrackNameScoped(IResolverContext r, object scopeName, bool throwIfNoScope, object item) =>
12153-
r.GetNamedScope(scopeName, throwIfNoScope)?.TrackDisposable(item);
12175+
item is IDisposable d ? r.GetNamedScope(scopeName, throwIfNoScope)?.TrackDisposableWithoutDisposalOrder(d) : item;
1215412176

1215512177
internal static readonly MethodInfo TrackNameScopedMethod =
1215612178
typeof(CurrentScopeReuse).GetTypeInfo().GetDeclaredMethod(nameof(TrackNameScoped));

0 commit comments

Comments
 (0)