We have a rather large EF code-first model that takes a long time to spin up. With EF5 & pre-compiled views, the load time was 30-45 seconds. However, after upgrading to EF6.1, the load time is > 3 minutes. All of this work is happening before it even starts looking at the precompiled views.
By pausing the debugger, I determined that nearly all time is being spent calling SequenceEqual inside the anonymous function created by TablePrimitiveOperations.GetPropertyPathMatcher (see the source). Using a profiler, I've confirmed that over 80% of the time is being spent in this method.
Are there any known fixes to this issue? I've posted it on Connect but I'm wondering if there's a workaround available currently.
It turns out this is an actual bug in EF 6.1.0. MSFT has created a fix which is available in the 6.1.1 beta and will be available in the 6.1.1 release.
Related
I have a project that has been a work in progress for several years. It is continually growing and changing. And our data layer project is now 10 times the size of any other project, and takes about 5 minutes to build on a pretty beefy dev box.
What stands out when I take a quick look through the project folders is that the data layer project is using Entity Framework Core, and it has a zillion migration scripts, each of which comes along with what appears to be a snapshot of the database schema in files called MigrationName.designer.cs.
This is very quaint and all, so I can look back to April 2018 (when we made our move to EF Core) and sip a beer with my colleagues as we reminisce about what our schema looked like then, and how very far we've come since then. But seriously, what the heck do we need all these dumb historical .designer.cs files for? Every time we make a migration, it's another 800KB of bloat in the codebase, and while I'm sure it doesn't translate to quite that much in the binaries, it's gotta have some cost. We're sure feeling it every time we have to compile.
Why do we need these files? Can we delete them?
I'm upgrading an old MVC web application from EF4 to EF6 (and MVC3 to MVC5) using a guide i found on SO.
Functionally appears OK, but I've noticed performance issues.
Specific requests on the prod env for this application running MVC3/EF4 finish in under half a second.
Same in my Dev system after update take seconds.
For comparison, I've created an new test MVC/EF6 solution on the same dev machine that I am working on the migrated application. I surfaced the below linq via an MCV action, and have found there is a big performance difference, between the two to applications.
Note: both the old and test application have no overheads in the controller constructor, they both only creating the dbContext, and run the query.
var sites = DB.Sites.Take(50).Include("Users").OrderBy(s => s.SiteName).ToList();
new test EF6 application: 200ms
old application upgraded: 2 seconds
I have profiled the requests on SQL Server, and I can't see any problem there.
I am considering removing the ADO Entity Framework from the old project and starting by adding again. but this was a model first application, and doing this appears to remove all the partial classes, where the metadata has been defined (resulting in lots of compilation errors).
Should I remove the ADO Entity Framework from the old project - and
recreate as a database first application?
Is there something I have missed - that could be causing the issue?
how can i find out where the time is being used?
Edit
I removed the ADO Entity Framework model(edmx) and rediscovered from the database. This resulted in a lot of refactoring, due to pluralisation difference between EF4 and EF6. There were also changes to the Add/Update/Delete entities behaviours.
This hasn't resolve the performance issue.
This ones going to be really hard to debug from afar but I'd start by capturing the query thats being created by ef with sql profiler and seeing if you're missing any indexes on the db. SQLServer is a temperamental beast when it comes to producing query plans and if EF has changed its queries from 4 to 6, and theres a reasonable amount of data in the tables, this is most likely to be causing your issue. You might find it just needs a new index or something along those lines.
Another option thats not specifically tied to your problem, but could have an effect is precompiling the views in the EF context, which should reduce the first query time after startup of the application.
Solved:
in the upgraded app's web.config I found the connection string had: Pooling=False; I removed this.
Additionally in my test app, I found the connectiton string had: App=EntityFramework
The performance immediately improved to that of the test application
I am querying for values from a database in AWS sydney, (I am in new zealand), using stopwatch i measured the query time, it is wildly inconsistent, sometimes in the 10s of milliseconds and sometimes in the hundreds of milliseconds, for the exact same query. I have no idea why.
Var device = db.things.AsQueryable().FirstOrDefault(p=>p.ThingName == model.thingName);
things table only has 5 entries, I have tried it without the asqueryable and it seems to make no difference. I am using visual studio 2013, entity framework version 6.1.1
EDIT:
Because this is for a business, I cannot put a lot of code up, another time example is that it went from 34 ms to 400 ms
thanks
This can be related to cold-warm query execution.
The very first time any query is made against a given model, the Entity Framework does a lot of work behind the scenes to load and validate the model. We frequently refer to this first query as a "cold" query. Further queries against an already loaded model are known as "warm" queries, and are much faster.
You can find more information about this in the following article:
https://msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
One way to make sure this is the problem is to write a Stored Procedure and get data by it(using Entity Framework) to see if the problem is in the connection or in the query(Entity Framework) itself.
I'm trying to root cause the issue with slow speed upon sign in in my EF6 web app hosted in azure. With all the research I've done I still don't quite understand why my app is behaving the way it is.
When I first deploy the app, and attempt to sign in, it's slow, this I understand why, and it's acceptable. Subsequent sign-ins and calls are relatively quick. What I don't understand is why if I don't interact with the application for maybe 5 minutes (even though my Azure Web App has Always On set to Enabled and is a Standard pricing tier Web App) the next login will be back down to taking 20+ seconds.
I don't quite understand what "First Run" means when anyone says it in regards to Entity being slow. Does it only mean, "the first time the web app is accessed by ANYONE", or does it mean something like, "When the dbContext is instantiated by ONE SPECIFIC client for the first time, that is THEIR specific first run, and their instance of the app/dbcontext whatever is now warmed up and ready"
The latter doesn't seem to make sense, because I can sign in on one machine, and move to another machine and it will be relatively quick as well.
"First time" means first dbContext use (query) after the application starts. But when app is iddle for some time, app pool is restarted and next time you enter the site it will start again. That's why EF takes time when there is no activity for some time.
Have a look at this post about app pool restart in azure
"First Run" would refer to the first time an EF query is run after the Entity Framework assemblies are loaded in to an app domain.
EF is a fairly large set of assemblies and they take a bit of time to load initially. On the first query they will also do a lot of work verifying the model. A lot of this time can be reduced by Pre-caching the views for the model (MSDN). For databases with a lot of mapped tables and stored procs this can be a quite a long time. I've had projects that could take up to 3 minutes to start up. Precaching reduced that to about 10 seconds. It does add quite a bit of complexity to managing schema changes though.
Before the Entity Framework can execute a query or save changes to the
data source, it must generate a set of mapping views to access the
database. These mapping views are a set of Entity SQL statement that
represent the database in an abstract way, and are part of the
metadata which is cached per application domain. If you create
multiple instances of the same context in the same application domain,
they will reuse mapping views from the cached metadata rather than
regenerating them. Because mapping view generation is a significant
part of the overall cost of executing the first query, the Entity
Framework enables you to pre-generate mapping views and include them
in the compiled project.
EDIT :
This question is not about compiled queries, it is about generating the EF database view at compile time.
From the ADO.NET team blog: Exploring the Performance of the ADO.NET Entity Framework - Part 1:
View Generation 56%– A big part of creating an abstracted view of the database is providing the actual view for queries and updates in the store’s native language. During this step, the store views are created. The good news is there is a way of making view generation part of the build process so that this step can be avoided at run time.
The first database call in my web app takes about 2.5 seconds instead of ~30 ms for subsequent identical calls.
I generated a precompiled view source file using the T4 template from the ADO.NET team blog, but it has made no detectable difference.
The T4 template takes about 2.5 seconds to run and the generated code compiles.
What am I missing?
Fixed it!
The Generated View derived from EntityViewContainer must be in the assembly that contains the STOs Self-Tracking Objects, not the one that contains the edmx model.
Your first call to your application after a build, the web server will have unloaded the application, and the first call "starts" the application again, and everything that is associated with that. This has nothing to do with pre-compiled views. Therefore, the first call will always take longer as the application is loaded.
Incidentally, the same thing will happen on your production server. An idle worker-pool might well unload your application, and the next call will load the application again, taking significantly longer to perform than usual requests.