Skip to content

Commit d6e7a27

Browse files
safihamidbrettsam
authored andcommitted
Fix for throughput impact on AppService plan.
When compiling Expressions during startup time, preferInterpretation will be set to true to significanly improve cold start in consumption mode however it will be set to false for premium and appservice plans to make sure throughput is not impacted there is no throughput drop in consumption with this setting.
1 parent 1207f9d commit d6e7a27

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/WebJobs.Script.WebHost/DependencyInjection/DryIoc/Container.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,22 +71,22 @@ namespace DryIoc
7171
public sealed partial class Container : IContainer
7272
{
7373
/// <summary>Creates new container with default rules <see cref="DryIoc.Rules.Default"/>.</summary>
74-
public Container() : this(Rules.Default, Ref.Of(Registry.Default), NewSingletonScope())
74+
public Container(bool preferInterpretation = false) : this(Rules.Default, Ref.Of(Registry.Default), NewSingletonScope(), preferInterpretation: preferInterpretation)
7575
{ }
7676

7777
/// <summary>Creates new container, optionally providing <see cref="Rules"/> to modify default container behavior.</summary>
7878
/// <param name="rules">(optional) Rules to modify container default resolution behavior.
7979
/// If not specified, then <see cref="DryIoc.Rules.Default"/> will be used.</param>
8080
/// <param name="scopeContext">(optional) Scope context to use for scoped reuse.</param>
81-
public Container(Rules rules = null, IScopeContext scopeContext = null)
82-
: this(rules ?? Rules.Default, Ref.Of(Registry.Default), NewSingletonScope(), scopeContext)
81+
public Container(Rules rules = null, IScopeContext scopeContext = null, bool preferInterpretation = false)
82+
: this(rules ?? Rules.Default, Ref.Of(Registry.Default), NewSingletonScope(), scopeContext, preferInterpretation: preferInterpretation)
8383
{ }
8484

8585
/// <summary>Creates new container with configured rules.</summary>
8686
/// <param name="configure">Allows to modify <see cref="DryIoc.Rules.Default"/> rules.</param>
8787
/// <param name="scopeContext">(optional) Scope context to use for <see cref="Reuse.InCurrentScope"/>.</param>
88-
public Container(Func<Rules, Rules> configure, IScopeContext scopeContext = null)
89-
: this(configure.ThrowIfNull()(Rules.Default) ?? Rules.Default, scopeContext)
88+
public Container(Func<Rules, Rules> configure, IScopeContext scopeContext = null, bool preferInterpretation = false)
89+
: this(configure.ThrowIfNull()(Rules.Default) ?? Rules.Default, scopeContext, preferInterpretation: preferInterpretation)
9090
{ }
9191

9292
/// <summary>Helper to create singleton scope</summary>
@@ -1417,6 +1417,10 @@ private Factory GetWrapperFactoryOrDefault(Request request)
14171417
private readonly IResolverContext _root;
14181418
private readonly IResolverContext _parent;
14191419

1420+
private readonly bool _preferInterpretation;
1421+
1422+
internal bool PreferInterpretation => _preferInterpretation;
1423+
14201424
internal sealed class InstanceFactory : Factory
14211425
{
14221426
public override Type ImplementationType { get; }
@@ -1927,7 +1931,8 @@ public Registry WithNoMoreRegistrationAllowed(bool ignoreInsteadOfThrow) =>
19271931
private Container(Rules rules, Ref<Registry> registry, IScope singletonScope,
19281932
IScopeContext scopeContext = null, IScope ownCurrentScope = null,
19291933
int disposed = 0, StackTrace disposeStackTrace = null,
1930-
IResolverContext parent = null, IResolverContext root = null)
1934+
IResolverContext parent = null, IResolverContext root = null,
1935+
bool preferInterpretation = false)
19311936
{
19321937
Rules = rules;
19331938

@@ -1942,6 +1947,7 @@ private Container(Rules rules, Ref<Registry> registry, IScope singletonScope,
19421947

19431948
_parent = parent;
19441949
_root = root;
1950+
_preferInterpretation = preferInterpretation;
19451951
}
19461952

19471953
#endregion
@@ -2022,7 +2028,7 @@ public static FactoryDelegateExpr WrapInFactoryExpression(this Expr expression)
20222028

20232029
/// <summary>First wraps the input service expression into lambda expression and
20242030
/// then compiles lambda expression to actual <see cref="FactoryDelegate"/> used for service resolution.</summary>
2025-
public static FactoryDelegate CompileToFactoryDelegate(this Expr expression)
2031+
public static FactoryDelegate CompileToFactoryDelegate(this Expr expression, bool preferInterpretation = false)
20262032
{
20272033
expression = expression.NormalizeExpression();
20282034

@@ -2046,8 +2052,8 @@ public static FactoryDelegate CompileToFactoryDelegate(this Expr expression)
20462052
return lambdaExpr.ToLambdaExpression().Compile();
20472053
#else
20482054
// Passing preferInterpretation: true as the default value of False uses JIT compile which has a huge impact on Functions cold start time
2049-
// This optimization is needed for Functions Host only and is not part of the DryIoc codebase which it was copied from.
2050-
return lambdaExpr.Compile(preferInterpretation: true);
2055+
// This optimization is needed for Functions Host only and is not part of the DryIoc codebase which it was copied from.
2056+
return lambdaExpr.Compile(preferInterpretation: preferInterpretation);
20512057
#endif
20522058
}
20532059

@@ -6574,7 +6580,8 @@ reuse is SingletonReuse && request.Rules.EagerCachingSingletonForFasterAccess &&
65746580
!request.TracksTransientDisposable &&
65756581
!request.IsWrappedInFunc())
65766582
{
6577-
var factoryDelegate = serviceExpr.CompileToFactoryDelegate();
6583+
var container = request.Container as Container;
6584+
var factoryDelegate = serviceExpr.CompileToFactoryDelegate(container != null ? container.PreferInterpretation : false);
65786585
var factory = factoryDelegate;
65796586

65806587
if (Setup.WeaklyReferenced)

src/WebJobs.Script.WebHost/DependencyInjection/JobHostServiceProvider.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ private Container BuildContainer(IServiceCollection descriptors)
6060
return new DelegateFactory(_ => _rootProvider.GetService(request.ServiceType));
6161
});
6262

63-
var container = new Container(r => rules);
63+
// preferInterpretation will be set to true to significanly improve cold start in consumption mode
64+
// it will be set to false for premium and appservice plans to make sure throughput is not impacted
65+
// there is no throughput drop in consumption with this setting.
66+
var preferInterpretation = SystemEnvironment.Instance.IsDynamic() ? true : false;
67+
var container = new Container(r => rules, preferInterpretation: preferInterpretation);
6468

6569
container.Populate(descriptors);
6670
container.UseInstance<IServiceProvider>(this);

src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProvider.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ public WebHostServiceProvider(IServiceCollection descriptors)
2929
throw new ArgumentNullException(nameof(descriptors));
3030
}
3131

32-
_container = new Container(_defaultContainerRules);
32+
// preferInterpretation will be set to true to significanly improve cold start in consumption mode
33+
// it will be set to false for premium and appservice plans to make sure throughput is not impacted
34+
// there is no throughput drop in consumption with this setting.
35+
var preferInterpretation = SystemEnvironment.Instance.IsDynamic() ? true : false;
36+
_container = new Container(_defaultContainerRules, preferInterpretation: preferInterpretation);
3337
_container.Populate(descriptors);
3438
_container.UseInstance<IServiceProvider>(this);
3539
_container.UseInstance<IServiceScopeFactory>(this);

0 commit comments

Comments
 (0)