Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perf: Reduce static memory footprint #3931

Closed
divega opened this issue Nov 30, 2015 · 5 comments
Closed

Perf: Reduce static memory footprint #3931

divega opened this issue Nov 30, 2015 · 5 comments
Labels
area-perf closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@divega
Copy link
Contributor

divega commented Nov 30, 2015

Some ad-hoc testing shows that EF7 currently has a static footprint of around 1 MB. I.e. once a DbContext has been created, used (e.g. to execute some queries), disposed and become unreachable, around 1 MB of the objects allocated by EF won't be freed up.

We believe there are two main classes of items that add up to this footprint:

  1. The service container we create and cache implicitly if the DbContext is created without an external service container.
  2. Individual private static fields in which we cache things that won't change such as MethodInfo instances, so that we don't need to reflect for them again.

I am creating this issue to give us a chance to discuss in triage what we can do about this. Here is atentative list of things to consider:

  1. We could document how to best work with EF7 in scenarios in which this memory footprint could become an issue. E.g. if using an external service provider helps we could consider making it more of a recommended pattern.
  2. We could try to reduce the memory footprint of services or objects we cache.
  3. We could stop caching certain objects if they are not that expensive to obtain again.
  4. We could look at using different patterns to our private static fields, e.g. we could move those to a singleton rooted on the service provider, change how we obtain MethodInfo instances to use the compiler (as suggested in Consider obtaining method infos from compiler generated expressions (may help with UWP/.NET Native) #3294) for extension methods, etc.
  5. We could expose a static API to clear up our static caches, including the implicitly created service container.
@divega divega changed the title Perf: Statically allocated memory Perf: Static memory footprint Dec 1, 2015
@rowanmiller rowanmiller added this to the 7.0.0 milestone Dec 1, 2015
@rowanmiller rowanmiller modified the milestones: 7.0.0-rc2, 7.0.0 Dec 2, 2015
@anpete
Copy link
Contributor

anpete commented Jan 7, 2016

I ran a more thorough analysis on the latest bits.

The scenario I tested was to execute a single query (Northwind Customers) using an external ServiceProvider, followed by disposing and nulling out both the DbContext and ServiceProvider.

The results look good:

mem

This table shows the managed memory usage at the end of the test program. We can see that we only retain ~2.2KB of objects from the Microsoft.* namespace.

Further I experimented with disabling static caching of MethodInfos in LinqOperatorProvider and the retained memory numbers were unchanged. It looks like these are cached at the CLR level.

@anpete anpete removed this from the 7.0.0-rc2 milestone Jan 7, 2016
@anpete anpete removed their assignment Jan 7, 2016
@divega
Copy link
Contributor Author

divega commented Jan 7, 2016

@anpete Thanks for doing the new analysis. 2.2 KB sounds really low and the fact that the MethodInfos didn't change anything is very interesting and great news.

I am trying to understand the results a bit better, and I have a couple of questions:

  1. How much of the ~ 516 KB spent in objects from System.* is part of EF's static footprint?
  2. Assuming the ~ 520 KB total showed in this table compares to the ~ 1 MB from your original observation, do you think the difference is due to improvements in the latest builds or is it because of changes in the experiment?

@anpete
Copy link
Contributor

anpete commented Jan 7, 2016

@divega

~13KB without EF in the picture at all (empty ServiceProvider).
~36KB with EF SQL Server enabled ServiceProvider (no DbContext).
~47KB with DbContext and Options (no query).
~60KB after Model creation.
~283KB after calling Database.ExecuteSqlCommand
~495KB after no-tracking LINQ query
~510KB after tracking LINQ query

@anpete
Copy link
Contributor

anpete commented Jan 7, 2016

@divega Re: improvements, I suspect it is a combination of improvements and a better experiment :-)

@rowanmiller
Copy link
Contributor

Team Triage: Based on analysis we are closing this out now as it seems the memory usage is mostly internal .NET caches and there isn't much to be improved within our stack.

@rowanmiller rowanmiller added this to the 7.0.0-rc2 milestone Jan 12, 2016
@rowanmiller rowanmiller changed the title Perf: Static memory footprint Perf: Reduce static memory footprint Jan 12, 2016
@ajcvickers ajcvickers removed this from the 1.0.0-rc2 milestone Oct 15, 2022
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Oct 15, 2022
@ajcvickers ajcvickers added this to the 1.0.0 milestone Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-perf closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

No branches or pull requests

4 participants