CacheMeIfYouCan (Enable o-space caching for Code First)
This change enables caching of o-space and o/c metadata when using Code First. This improves the perf for creating new DbContext instances with Code First.
Details: Code First uses a cached MetadataWorkspace inside DbCompiledModel. This workspace is used to construct an EntityConnection each time a DbContext instance is initialized, which is in turn used to create the underlying ObjectContext. ObjectContext would previously create a shallow copy of this workspace for use. This shallow copy ensures that any item collections loaded into the workspace in use are not loaded into the workspace that was originally passed to EntityConnection. In other words, it ensures that o-space and o/c metadata is discarded when the ObjectContext is discarded.
The change is to not perform the shallow copy so that as o-space and o/c metadata is discovered and loaded it is added to the cached MetadataWorkspace and is re-used for all subsequent context instances. This requires that the creation and update of o-space and o/c metadata (which is done incrementally unlike the other collections) is now thread-safe. Even though this happens incrementally the normal use cases for EF involve adding to it very infrequently and reading from it a lot. Therefore the thread-safety is done in such a way that reads should remain about as fast as they were before. This involves both adding to the underlying item collection and also keeping two indexes updated for o/c metadata.
Note that caching for EDMX-based contexts uses a different mechanism and so o-space metadata is still not cached for these cases. This is something that can be looked into as part of simplifying the non-Code First metadata caching.
This is my simple test code that does little more than create and initialize a DbContext:
for (int i = 0; i < 100000; i++)
{
using (var context = new BlogContext())
{
context.Blogs.Create();
}
}
Note that this code runs after one context instance has already been created and initialized so that warm-up time is not included in the test. In runs on my machine the change improves the perf here by approximately 30%. Note that this test does not perform any database access. The perf improvement when database access also happens will be much smaller, and probably not even noticeable in many scenarios.
↧