Closed ArtemAvramenko closed 10 months ago
Hello @ArtemAvramenko ,
Are you including the time that EF Core use to JIT compile itself? Our library is very small compared to everything that EF Core had to compile to execute the first query. Even if you use our library, we still use EF Core and you cannot include the part when calculating the time of JIT.
Best Regards,
Jon
Hello @JonathanMagnan,
I certainly removed Futures for comparison. CPU load drops several times after that and Time spent in JIT becomes equal to zero.
I certainly removed Futures for comparison
Did you add these 2 lines to have a good comparison?
var users = context.Users.ToList();
var companies = context.Companies.ToList();
From what I remember, this is when you make the first query that EF Core will JIT compile most of his method. I feel it weird that the JIT compile will be close to zero without our library. We will surely investigate more if you tell me this is the behavior you still have.
@JonathanMagnan Yes, that's exactly the code I was comparing it to. With it, JIT compilation is called only at the first call. But if Futures
are added, then each time Test()
is called, new +4 methods are generated.
The problem remains in version 8.x
Hello @ArtemAvramenko ,
We made some progress in finding out exactly where the JIT issue started, but to be honest, I'm not sure if we will be able to fix it or not.
We will look one more time to find out exactly if we can skip a line of code that causes it or not.
Hello @ArtemAvramenko ,
We made more investigation this week, and I believe we will simply close as work as intended
When creating a query, EF Core compiles it and caches the query plan. So the next time the same query is called, it doesn't longer require JIT compile or at least calls some method that causes a JIT compile, such as the one found here: https://github.com/dotnet/efcore/blob/397dc68aa9599f3fd7bf04b5e447614dfd3f90c2/src/EFCore/Query/QueryCompilationContext.cs#L169
So it explain why the JIT compile is 0 when running the query multiple times without our library.
On our side, the query is always re-created as we combine them. We don't cache the plan either. So we always need to execute some of the code and the visitor found in my previous link every time.
Could it be possible to improve this to reduce the JIT compile time? Surely, but at this point, I believe we are currently too deep in methods specific to EF Core to really make it happen.
Let me know if at least the explanation makes sense.
Best Regards,
Jon
Hello @JonathanMagnan,
I imagined it was possible to cache the result without recompiling again. But obviously there will be a lot of pitfalls, such as different SQL that EF generates depending on the parameter values. This and many other things will have to be taken into account when creating the cache.
At the moment, I will try to remove the use of EntityFramework-Plus and see how negatively it will affect the load on the database. A slight increase in the load on the database will be acceptable to me, as it will significantly reduce the application's load on the CPU.
1. Description
I've been checking what resources are being spent on in my application and found that a significant amount of time is spent on JIT compilation. As it turns out, the reason is the use of
Futures
.2. Exception
Test application metrics (the same thing happens in a real application):
It would be great if EntityFramework-Plus would cache compilation results so that performance would increase dramatically.
3. Fiddle or Project
Even the simplest example reveals the problem:
Full code - https://gist.github.com/ArtemAvramenko/46afef540b1def14d42a9c24f272c745
4. Any further technical details
I used dotnet-counters to collect the metrics.
Update: If you remove
Futures
from the code, the "Number of Methods Jitted" metric stops growing and "Time spent in JIT" becomes zero.