94

I have followed the "Don't Optimize Prematurely" mantra and coded up my WCF Service using Entity Framework.

However, I profiled the performance and Entity Framework is too slow. (My app processes 2 messages in about 1.2 seconds, where the (legacy) app that I am re-writing does 5-6 messages in the same time. (The legacy app calls sprocs for its DB Access.)

My profiling points to Entity Framework taking the bulk of the time per message.

So, what are my options?

  • Are there better ORMs out there?
    (Something that just supports normal reading and writing of objects and does it fast..)

  • Is there a way to make Entity Framework faster?
    (Note: when I say faster I mean over the long run, not the first call. (The first call is slow (15 seconds for a message), but that is not a problem. I just need it to be fast for the rest of the messages.)

  • Some mysterious 3rd option that will help me get more speed out of my service.

NOTE: Most of my DB interactions are Create and Update. I do very very little selecting and deleting.

Sнаđошƒаӽ
  • 13,406
  • 11
  • 67
  • 83
Vaccano
  • 70,257
  • 127
  • 405
  • 747
  • This sounds like a rehash of 'linq is slow' how do you know it's EF? Have you profiled all your changes? – Maess Dec 01 '11 at 20:25
  • 6
    Some of the answers are pointing to the queries. In my experience, slowness in EF has little to do with the queries but instead with the costs of materialization, and those costs are often tied to change tracking and how that affects the instance(s) created. Unfortunately, I don't have a silver bullet for you so this is just a comment, but I would recommend seeing if profiling reveals high materialization costs and, if so, research what can be done about said costs. – Anthony Pegram Dec 01 '11 at 20:26
  • @Maess - I thought I indicated that I had profiled and found that it was EF/DB that was slow. Either way, yes I did. I profiled it and it is EF/DB interactions that are the major culprit. – Vaccano Dec 01 '11 at 20:56
  • @Anthony - Isn't materialization first run kind of things? If so, you are right that it is very slow. The first run is super slow. But as I indicated, I am not too worried about that. It is total throughput that is the problem. (If that is not what Materialization is then I need to so some research to see if it is the cause of my issue) – Vaccano Dec 01 '11 at 20:58
  • 1
    @Vaccano, no, materialization is the process of taking the data from the database and instantiating and populating the graph of objects to represent that data. I'm not talking about first run performance as the code is jitted (or even as Sql Server might create the query execution plan), but what happens each and every time you get data in the form of objects. – Anthony Pegram Dec 01 '11 at 21:13
  • @Anthony - I will look into that then. Maybe there is a way to speed that up. – Vaccano Dec 01 '11 at 21:47
  • I'd really recommend to go into details what's exactly the code you write to insert and update entities (preferably in a new question to be fair to the people who have already answered your current question) before you think about radical steps like changing the ORM. You don't say which version of EF you are using, if you use POCOs, if you use dynamic proxies, if you have automatic change detection enabled, etc. I have seen in my own insert/update code performance differences by a factor of 50 (= fifty) depending on such details. – Slauma Dec 01 '11 at 22:40
  • A few links about what I mean with my previous comment: 1) http://stackoverflow.com/q/5943394/270591, 2) http://stackoverflow.com/q/5917478/270591, 3) http://stackoverflow.com/q/5940225/270591, 4) http://stackoverflow.com/q/5798646/270591. None of them or all of them might be applicable to your situation. It just depends on the details of your settings and your code. – Slauma Dec 01 '11 at 22:49
  • Entity Framework is significantly faster in .net 4.5 http://www.outofmemory.co.uk/entity-framework-5-dramatically-faster-in-net-4-5/ – Andrew Rimmer Oct 26 '12 at 13:01
  • @AndrewRimmer - for first run it is faster... Not much is done for the normal "middle of the app" processing. – Vaccano Jul 02 '13 at 17:46
  • Entity Framework is slow? I think not. Stackoverflow is working proof. If there is a problem with EF having abnormal latency it's with the developer. Simple as that. – Noah R Dec 14 '13 at 23:33
  • I am involved with a large app using EF and the SQL queries it generates can be very slow. I am not saying don't use it, but be prepared to step out of it and use stored procedures when you have issues. The stored procedures can still be called from EF and you cant still unit test and use a repository pattern etc This assumes you have confirmed the SQL is the problem. – Jonathan Shields Aug 08 '16 at 11:16
  • 1
    EF was really designed to be flexible with any data source and that's its greatest power, however, if you're always using MS-SQL, there isn't much point in not using stored procedures w/EF (and, perhaps, not using EF at all - as it certainly adds more "what is it doing now?" questions in the development process). If you hate obfuscation or need fine tuned control, EF is not for you. On really complex projects EF, honestly, takes longer to debug, overall (and easier to fry a database!). – MC9000 Dec 28 '18 at 07:05

13 Answers13

81

The fact of the matter is that products such as Entity Framework will ALWAYS be slow and inefficient, because they are executing lot more code.

I also find it silly that people are suggesting that one should optimize LINQ queries, look at the SQL generated, use debuggers, pre-compile, take many extra steps, etc. i.e. waste a lot of time. No one says - Simplify! Everyone wants to comlicate things further by taking even more steps (wasting time).

A common sense approach would be not to use EF or LINQ at all. Use plain SQL. There is nothing wrong with it. Just because there is herd mentality among programmers and they feel the urge to use every single new product out there, does not mean that it is good or it will work. Most programmers think if they incorporate every new piece of code released by a large company, it is making them a smarter programmer; not true at all. Smart programming is mostly about how to do more with less headaches, uncertainties, and in the least amount of time. Remember - Time! That is the most important element, so try to find ways not to waste it on solving problems in bad/bloated code written simply to conform with some strange so called 'patterns'

Relax, enjoy life, take a break from coding and stop using extra features, code, products, 'patterns'. Life is short and the life of your code is even shorter, and it is certainly not rocket science. Remove layers such as LINQ, EF and others, and your code will run efficiently, will scale, and yes, it will still be easy to maintain. Too much abstraction is a bad 'pattern'.

And that is the solution to your problem.

Sean
  • 1,173
  • 6
  • 2
  • 161
    This is throwing the baby out with the bathwater. You optimize bottlenecks, it's silly to throw EF out because it's too slow in a few places, while being plenty fast in most others. Why not use both? EF handles stored procedures and raw SQL just fine. I just converted a LINQ-to-SQL query that took 10+ seconds into a SP that takes ~1 second, but I'm not gonna throw all LINQ-to-SQL out. It saved a LOT of time in other simpler cases, with less code and less room for error and the queries are compiler verified and match the database. Less code is easier maintenance and less room for errors. – JulianR Dec 29 '11 at 18:11
  • 12
    Overall your advice is good though, but I don't think it's right to abandon EF or other abstractions because they don't work well 10% of the time. – JulianR Dec 29 '11 at 18:13
  • 51
    Plain SQL = easy to maintain? Just not true for very large apps with lots of business logic. Writing complex reusable SQL is not an easy thing to do. Personally I have had some performance issues with EF, but these problems simply don't compare to the benefits of a proper ORM in terms of a RAD and keeping things DRY (if there's any level of complexity involved). – MemeDeveloper Mar 22 '12 at 12:08
  • 4
    Sean - I fully agree with you. Plain ADO.Net code is the fastest I have come across in 10 years of my .Net programming life. All these ORM Frameworks do cause extra code to execute, and extra code takes extra time to execute and extra resources. The only advantage I see of these frameworks is that they could save development time but at the expense of making the app slower and very very code-heavy. Personally, I feel that when developers are too lazy to write ADO.Net code then they use these frameworks. Its an easy way out in my opinion, or it could just be pressure from project manager. – Sunil May 18 '12 at 15:32
  • 13
    +10^100 Too much abstraction is a bad 'pattern' – Makach Nov 05 '12 at 22:30
  • 61
    -1. "EF will ALWAYS be slow and inefficient." I don't see why you would assert something like this to be the absolute truth. Having more layers to go through will make something slower, but whether that difference is even NOTICEABLE is completely dependent on the situation like the amount of data and the type of query being executed. To me this is the same thing as saying 'C# will ALWAYS be slow and inefficient' because it is a higher abstraction than C++. Yet many people choose to use it because the productivity gains far out weigh performance loss (if there is any). The same applies to EF – Despertar Dec 06 '12 at 01:49
  • 3
    OK, so let's take 10^100 development time to create something as using tried and true tools. The it's too slow argument is almost ALWAYS because the developer doesn't understand how to optimize code. – Nick Turner Jul 24 '13 at 13:44
  • 10
    For what it's worth, I've kind of revisited my opinion displayed in that old comment here. We've since thrown out EF in favor of SQL queries through Dapper with a custom change tracker for inserts/updates/deletes. It has downsides, but just *knowing* how something will perform and behave because you control all parts of the process is really valuable. I still don't consider EF to be bad, but I probably wouldn't take up the dependency for a project that I know will require high performance and complex data access. – JulianR Dec 14 '13 at 23:50
  • 5
    You cannot write something that significantly simplifies large software problems in a generic way that does not come with a significant performance cost. There has to be a lot of code to handle the wide variety of cases to which the problem applies. There is a necessary trade off with generic and scope of problem on the one hand and performance on the other. –  Feb 26 '14 at 18:57
  • I stopped using Entity Framework in favor of PetaPoco. – The Muffin Man Aug 09 '14 at 07:09
  • 3
    Amen to that... Obfuscation by Complication.. – calcazar Oct 22 '15 at 15:18
  • 1
    If I could give this a +3 I would. Time and time again, I keep trying to use things like EF Core w/ SQLite for UWP/Xamarin apps. Time and time again, it all sounds great on paper, then I go through and find that the framework doesn't support everything, like EF Core right now doesn't support lazy loading, or an index attribute, you have to do things manually. So I properly indexed my tables by editing the DB manually, load it up, as soon as you put in FKs into the mix EF crawls. ORMs are sad for complex joins usually and even sometimes simple joins, I say go with SQL too. Tell it on tha mount. – John Ernest Apr 12 '17 at 02:35
  • 2
    100% agree with this answer. I honestly feel like ORM and EF is such a backwards step. I've had 20 years experience in development, and have worked on extremely large systems. SQL is orders of magnitude faster and more efficient than EF. EF is only good for developers who don't know SQL well enough and need hand holding by layers of bloated architecture. – Manachi Feb 13 '18 at 01:55
  • How is SQL any harder to maintain? Black box code (what EF is) is fantastic, that is, until, you need to do something special, then you can spend days with a team pulling their hair out trying to figure out what went wrong. I don't see a problem with letting SQL do more crunching on it's end, not to mention, with EF, you're screwed if other apps need access to the database (which is what Enterprise level software is all about)! – MC9000 Mar 29 '19 at 16:32
  • This is a fast moving world now and even more faster and we got less or no time.. We cant just throw EF like we throw garbage.. it is not always the car, Sometimes the driver matters too... – Thameem May 01 '21 at 10:37
47

You should start by profiling the SQL commands actually issued by the Entity Framework. Depending on your configuration (POCO, Self-Tracking entities) there is a lot room for optimizations. You can debug the SQL commands (which shouldn't differ between debug and release mode) using the ObjectSet<T>.ToTraceString() method. If you encounter a query that requires further optimization you can use some projections to give EF more information about what you trying to accomplish.

Example:

Product product = db.Products.SingleOrDefault(p => p.Id == 10);
// executes SELECT * FROM Products WHERE Id = 10

ProductDto dto = new ProductDto();
foreach (Category category in product.Categories)
// executes SELECT * FROM Categories WHERE ProductId = 10
{
    dto.Categories.Add(new CategoryDto { Name = category.Name });
}

Could be replaced with:

var query = from p in db.Products
            where p.Id == 10
            select new
            {
                p.Name,
                Categories = from c in p.Categories select c.Name
            };
ProductDto dto = new ProductDto();
foreach (var categoryName in query.Single().Categories)
// Executes SELECT p.Id, c.Name FROM Products as p, Categories as c WHERE p.Id = 10 AND p.Id = c.ProductId
{
    dto.Categories.Add(new CategoryDto { Name = categoryName });
}

I just typed that out of my head, so this isn't exactly how it would be executed, but EF actually does some nice optimizations if you tell it everything you know about the query (in this case, that we will need the category-names). But this isn't like eager-loading (db.Products.Include("Categories")) because projections can further reduce the amount of data to load.

J. Tihon
  • 4,359
  • 22
  • 19
  • I made some assumptions in the example (like Product.Categories being lazy loaded), but they are only used to illustrate the benefit of projections. – J. Tihon Dec 01 '11 at 20:35
  • 42
    This response sounds reasonable, until you realize that anonymous types are not accessible outside of the method in which they're defined. If you want to load up a complex object and not write a megamoth, you then need to deserialize your new anonymous types into some kind of POCO. Again, that almost sounds reasonable until you realize that in doing so you have essentially REWRITTEN YOUR OWN ENTITY FRAMEWORK. Which is bullshit. – Doug Jan 30 '13 at 13:44
  • 5
    this resulted in a 15x-20x increase in speed for me. – Dave Cousineau Mar 08 '13 at 21:09
  • 12
    Interesting and helpful reply, still valid quite some time later. @Doug: Which is not really bullshit since you only optimise (using projections) those few queries where you really need use the extra benefit. EF and POCO gives you reasonable default, which is very nice! – Victor Jan 16 '14 at 21:49
  • 2
    @Doug Most applications have view models for view-only scenarios, right? Might as well do as much of the mapping as you pull out the data. – Casey Aug 26 '15 at 15:58
  • Do you have an idea about the methods used in scaffolding like db.athlete.find(id) etc. How do they perform in comparison with Dapper?? – It's a trap Mar 21 '16 at 09:29
  • 4
    I use to feel ORM's were the future. They just made sense, until I started using them. Then I found [Dapper](https://github.com/StackExchange/dapper-dot-net). Now, when seeing solutions like this, I cringe at how the complexity ramps up quickly. Writing abstracted SQL in C# is no way to go through life. – Michael Silver Jun 02 '16 at 15:26
  • I hated ORM's from the moment i saw them, and I still do to this day. – Manachi Feb 13 '18 at 01:48
38

One suggestion is to use LINQ to Entity Framework only for single-record CRUD statements.

For more involved queries, searches, reporting, etc, write a stored procedure and add it to the Entity Framework model as described on MSDN.

This is the approach I've taken with a couple of my sites and it seems to be a good compromise between productivity and performance. Entity Framework will not always generate the most efficient SQL for the task at hand. And rather than spending the time to figure out why, writing a stored procedure for the more complex queries actually saves time for me. Once you're familiar with the process, it's not too much of a hassle to add stored procs to your EF model. And of course the benefit of adding it to your model is that you get all that strongly typed goodness that comes from using an ORM.

Steve Wortham
  • 20,322
  • 4
  • 62
  • 86
  • Do you have an idea about the methods used in scaffolding like db.athlete.find(id) etc. How do they perform in comparison with ADO.NET or dapper?? – It's a trap Mar 22 '16 at 05:25
15

If you're purely fetching data, it's a big help to performance when you tell EF to not keep track of the entities it fetches. Do this by using MergeOption.NoTracking. EF will just generate the query, execute it and deserialize the results to objects, but will not attempt to keep track of entity changes or anything of that nature. If a query is simple (doesn't spend much time waiting on the database to return), I've found that setting it to NoTracking can double query performance.

See this MSDN article on the MergeOption enum:

Identity Resolution, State Management, and Change Tracking

This seems to be a good article on EF performance:

Performance and the Entity Framework

aledpardo
  • 705
  • 10
  • 19
JulianR
  • 15,427
  • 3
  • 48
  • 84
  • 9
    Before anyone does this, it might be a good idea to have a read here. http://stackoverflow.com/questions/9259480/entity-framework-mergeoption-notracking-bad-performance – leen3o Dec 11 '12 at 19:32
6

You say that you have profiled the application. Have you profiled the ORM too? There is an EF profiler from Ayende that will highlight where you can optimise your EF code. You can find it here:

http://efprof.com/

Remember that you can use a traditional SQL approach alongside your ORM if you need to to gain performance.

If there a faster/better ORM? Depending on your object/data model, you could consider using a one of the micro-ORMs, such as Dapper, Massive or PetaPoco.

The Dapper site publishes some comparitive benchmarks that will give you an idea how they compare to other ORMs. But it's worth noting that the micro-ORMs do not support the rich feature set of the full ORMs like EF and NH.

You may want to take a look at RavenDB. This is a non-relational database (from Ayende again) that lets you store POCOs directly with no mapping needed. RavenDB is optimised for reads and makes the developers life a whole lot easier by removing need to manipulate schema and to map your objects to that schema. However, be aware that this is a significantly different approach to using an ORM approach and these are outlined in the product's site.

jao
  • 17,118
  • 13
  • 58
  • 92
Sean Kearon
  • 9,322
  • 12
  • 69
  • 88
4

I have found the answer by @Slauma here very useful for speeding things up. I used the same sort of pattern for both inserts and updates - and performance rocketed.

Community
  • 1
  • 1
MemeDeveloper
  • 5,845
  • 2
  • 38
  • 52
2

From my experience, the problem not with EF, but with ORM approach itself.

In general all ORMs suffers from N+1 problem not optimized queries and etc. My best guess would be to track down queries that causes performance degradation and try to tune-up ORM tool, or rewrite that parts with SPROC.

Community
  • 1
  • 1
Valera Kolupaev
  • 2,225
  • 14
  • 14
  • 2
    People keep telling me this. But I will set up a simple select statement using old school ADO, and the same simple select using an EF context and EF is always considerably slower. I really want to like EF, but it keeps making life harder instead of easier. – Sinaesthetic Jun 22 '14 at 23:33
  • 1
    @Sinaesthetic Of course it's slower. By the same token, code written using Linq to Objects is usually slower than code written without it. The question is not *really* whether it's faster or as fast (how could it be, when under the hood it still has to issue the query you were issuing by hand?) but whether 1) it's still fast enough for your needs 2) it saves you time writing the code 3) the benefits offset the costs. Based on those items I think EF is appropriate for lots of projects. – Casey Aug 26 '15 at 17:33
  • @Sinaesthetic I'd also add that if you don't use an ORM, what happens more often than not is not that each SQL query is fine-tuned and optimized but that the application ends up developing an in-house, organic, poorly-supported, poorly-performing ORM, unless your team is exceptionally disciplined and very concerned about performance. – Casey Aug 26 '15 at 17:35
1

This is simple non-framework, non-ORM option that loads at 10,000/second with 30 fields or so. Running on an old laptop, so probably faster than that in a real environment.

https://sourceforge.net/projects/dopersistence/?source=directory

Andrew
  • 11
  • 1
1

I ran into this issue as well. I hate to dump on EF because it works so well, but it is just slow. In most cases I just want to find a record or update/insert. Even simple operations like this are slow. I pulled back 1100 records from a table into a List and that operation took 6 seconds with EF. For me this is too long, even saving takes too long.

I ended up making my own ORM. I pulled the same 1100 records from a database and my ORM took 2 seconds, much faster than EF. Everything with my ORM is almost instant. The only limitation right now is that it only works with MS SQL Server, but it could be changed to work with others like Oracle. I use MS SQL Server for everything right now.

If you would like to try my ORM here is the link and website:

https://github.com/jdemeuse1204/OR-M-Data-Entities

Or if you want to use nugget:

PM> Install-Package OR-M_DataEntities

Documentation is on there as well

TheMiddleMan
  • 675
  • 7
  • 15
0

I used EF, LINQ to SQL and dapper. Dapper is the fastest. Example: I needed 1000 main records with 4 sub records each. I used LINQ to sql, it took about 6 seconds. I then switched to dapper, retrieved 2 record sets from the single stored procedure and for each record added the sub records. Total time 1 second.

Also the stored procedure used table value functions with cross apply, I found scalar value functions to be very slow.

My advice would be to use EF or LINQ to SQL and for certain situations switch to dapper.

tfa
  • 1,104
  • 10
  • 16
0

It only makes sense to optimize after you've profiled. If you find out that the DB access is slow, you can convert to using stored procedures and keep EF. If you find out that it's the EF itself that's slow, you may have to switch to a different ORM or not use an ORM at all.

Gabe
  • 79,868
  • 10
  • 131
  • 226
0

We have an similar application (Wcf -> EF -> database) that does 120 Requests per second easily, so I am more than sure that EF is not your problem here, that being said, I have seen major performance improvements with compiled queries.

Andrei
  • 36,642
  • 31
  • 139
  • 196
np-hard
  • 5,445
  • 4
  • 47
  • 73
  • 98% of my code is Create and Update calls. I don't know if that makes a difference, but it is much slower than 120 per second. – Vaccano Dec 01 '11 at 21:45
  • yeah that would not be a typical application, i would suggest you profile your application. for us its mostly reads... – np-hard Dec 01 '11 at 22:56
-1

The Entity Framework should not cause major bottlenecks itself. Chances are that there are other causes. You could try to switch EF to Linq2SQL, both have comparing features and the code should be easy to convert but in many cases Linq2SQL is faster than EF.

Wiktor Zychla
  • 44,107
  • 6
  • 65
  • 91