New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider expression interpretation to speed-up first time resolution #45
Comments
Hi @dadhi , the thing is that |
Yep, I know :) But the idea is different, I am talking about first-time resolution where compiling expression + calling result delegate is much slower than |
Oh, ok, I get the idea :) |
Other things to consider:
|
Remaining work:
|
…g and controlling method into the Factory.TryInterpretation #45
BenchmarkHere is the source. DryIoc setup as an example, the rest of the containers do the same. public static DryIoc.IContainer PrepareDryIoc()
{
var container = new Container();
container.Register<Parameter1>(Reuse.Transient);
container.Register<Parameter2>(Reuse.Singleton);
container.Register<ScopedBlah>(Reuse.Scoped);
return container;
}
public static object Measure(DryIoc.IContainer container)
{
using (var scope = container.OpenScope())
return scope.Resolve<ScopedBlah>();
} Register, then Open Scope and Resolve for the first time[Benchmark(Baseline = true)]
public object BmarkDryIoc() => Measure(PrepareDryIoc()); Results:
Open Scope and Resolve for the first timeprivate static readonly DryIoc.IContainer _dryioc = PrepareDryIoc();
[Benchmark(Baseline = true)]
public object BmarkDryIoc() => Measure(_dryioc); Results:
|
Here is state of fast .NET DI containers in certain (not uncommon) scenario, or in other words: always treat benchmarks in context! Comparing to the benchmark above, I have just added a scoped dependency. DryIoc at the moment does not support interpreting of scoped dependency, because it uses the nested lambda expression. CreateContainerAndRegister_FirstTimeOpenScopeResolve:
FirstTimeOpenScopeResolve:
PS. MS.DI performs great for what it designed 👍 (again, in this specific start-up / first resolution scenario). |
Hi @dadhi , |
@ahydrax |
Considering that @jeremydmiller has just announced the Lamar 2.0 release, let's check it out too because it uses yet another approach with Roslyn based compilation. But I expect it to perform slower in the above use-case exactly because of the approach. Let see. |
Here are the results with SimpleInjector.
FirstTimeOpenScopeResolve.BmarkSimpleInjector:
|
@dadhi "But I expect it to perform slower in the above use-case exactly because of the approach." A big yes and maybe no. If you're using it simply, yeah, the cold start time isn't super awesome on the first usage of Roslyn, but they (Roslyn team) have made huge strides on that one. Lamar also has a model where it can drop the generated C# code into your code once, and just use the already compiled resolver strategies for much, much faster cold start times. |
This is super interesting. How I can test that? |
Shame on me, I haven't written any docs for that. Let me write a blog post on that and all the struggles I went through w/ optimizing cold start. And then you know that Lamar uses bits and pieces of ImTools and its own copy of FastExpressionCompiler for internal types. So even if Lamar is competitive, you still get credit;-) |
Hey, the benchmark with first version of DryIoc with scoped dependency interpretation:
Btw: @jeremydmiller, Here is mine heads-on benchmark with Lamar v2. Adding it here just for reference:
|
For completeness, here is the OpenScope-Resolve-Dispose load (your usual Unit-of-Work or Request) after the warmup (5 times the cycle):
Again, we should benchmark a more real-world object graph (maybe 10 level deep and 5 to 10 dependencies wide on each level, with a variety of lifestyles). Current setup is a 2 level root with 3 dependencies. Take it into account when looking at the benchmarks. |
Psst, here's a cheap way to do more realistic benchmarking: https://github.com/JasperFx/lamar/tree/master/src/Benchmarks. Use an ASP.net Core app to quickly get yourself a much better set of registrations. |
Considering complete. |
…penGenerics optimized and cleaned up rule selection a bit
…for OpenGenerics optimized and cleaned up rule selection a bit
Idea is to have fast first-time (cold start) performance, and compile and cache the expression in parallel to have a later fastest performance.
Assumptions:
Activator.CreateInstance
much faster thanExpression.Compile
.Compile
+ cachingIf the assumptions are true, we may try do both the expression creation and
Activator.CreateInstance
. Then schedule expression to ThreadPool and return activated instance right away.The text was updated successfully, but these errors were encountered: