Entity Framework Query Caching


Senior Application Development Manager, Deepak Malik, explains the Query caching behavior, performance implications, and extensibility provided in the latest release of Entity Framework


Caching entities or query results has been a recommended practice for application development to improve an application's performance especially in data centric applications. It is very simple to understand.  The first time a query is invoked, data is retrieved from the database and stored in memory before being returned. The compiled queries could be cached for the life of an app pool instance and provided to the Entity Framework for low latency performance of data access.

Before Entity Framework 6, the framework has a hard coded limit of 800 Compiled Queries and removes additional compiled queries after that threshold is exceeded which could cause significant performance issues. The EF QueryCacheManager will continually trim this cache every minute which can cause further locking issues under load.

These symptoms might occur frequently during load conditions when the number of objects in cache crosses the threshold and may impact interactive users.  Operationally, the increased processing volumes may cause an application to use two to three times (2x-3x) more private memory then normally used.  Under these conditions, there is more memory pressure and Garbage Collector (GC) overhead (which impacts all operations) which results in higher latency.

EF QueryCacheManager has these values hard coded as follows:

clip_image002

Figure 1- https://referencesource.microsoft.com/#System.Data.Entity/System/Data/Common/QueryCache/QueryCacheManager.cs

The creation of the QueryCacheManager is done with those constants:

  private QueryCacheManager(int maximumSize, float loadFactor, int recycleMillis)

  {

      <…>

//

// Load hardcoded defaults

//

this._maxNumberOfEntries = maximumSize;

//

// set sweeping high mark trigger value

//

this._sweepingTriggerHighMark = (int)(_maxNumberOfEntries * loadFactor);

//

// Initialize Recycler

//

this._evictionTimer = new EvictionTimer(this, recycleMillis);         

   }

In EF 6.1.2 and later versions the parameters of the query cache can be configured only via the EntityFramework section in the application’s .config file. For example, an initial size of 10,000 entries and a clearing interval of two minutes can be specified like this:

<entityFramework>

<queryCache size='10000' cleaningIntervalInSeconds='120'/>

</entityFramework>

Currently, there is no other method nor programmatic API to configure the cache during runtime with EF6.


Premier Support for Developers provides strategic technology guidance, critical support coverage, and a range of essential services to help teams optimize development lifecycles and improve software quality.  Contact your Application Development Manager (ADM) or email us to learn more about what we can do for you.

Comments (4)

  1. Tor Arne Gustad says:

    Thanks for an interesting read! It does however raise some new questions:

    What are the negative impacts of increasing the query cache size? I guess memory usage is one, but will the application slow down if we increase the query cache to, say, 100 000 entries?

    Also, how much memory (on average) does a single query cache entry use?

    Thanks!

    1. Deepak Malik says:

      Hey Tor,

      There is no negative impact if the machine supports the resulting cache size (based on number and size of entities) and this feature is currently available in Entity Framework 6.
      Product team has released a fix for Entity framework 4 on 16 May 17 as part of May 2017 Preview of Quality Rollup for .NET release. Here are some pointers:
      Windows 8.1 and Server 2012 R2: https://support.microsoft.com/en-us/help/4019290
      Windows Server 2012: https://support.microsoft.com/en-us/help/4019289
      Windows 7 and Server 2008 R2 SP1: https://support.microsoft.com/en-us/help/4019288
      Windows Server 2008 SP2: https://support.microsoft.com/en-us/help/4019291

      To your point on average size, it depends on the entity size. The limit is on number of entities in cache and not size. 800 entities of 10 KB generate the cache size of 8 MB, if machines supports it, the application will provide the needed performance.

      This is addressing the issue cache cleanout as number of entities goes beyond limit irrespective of size.

      1. Tor Arne Gustad says:

        Hi,

        thank you for answering this so quickly. We have a number of queries which isn’t optimized for parameterization yet, and I suspect these are pushing the parameterized queries out of the cache in some cases.

        We are currently on EF v6.1.3, so I will increase the number right away and watch how the memory usage changes over time.

        1. Deepak Malik says:

          Let me know Tor if you face any issues and will be happy to help

Skip to main content