-
Notifications
You must be signed in to change notification settings - Fork 10.2k
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
Blazor Server Memory Usage #39238
Comments
Hi @gregoryagu You might be holding on to a DbContext too long, can you tell me how you instantiate the DbContext? There are some recommendations for using EF Core with Blazor server here: that might help you. |
@MariovanZeist This is the code that creates the context: For most data operations, this is the code that is used:
However, there is some data which is retrieved, tracked, and then saved to the database. For this:
This is what the dispose looks like:
So, as far as I know, i am coding this correctly per the guidance. |
Hi @gregoryagu I personally have deployed multiple applications that use Blazor Server and EF Core heavily without issues, And as you state that your application is only run concurrently by 10 users, my opinion is that you shouldn't run into memory problems. My guess is that something is holding on to memory, as apparent by the need of that last line of code in the dispose: this.GetType().GetProperties().Where(prop => prop.PropertyType.Name.StartsWith(nameof(BindableCollection<string>)) || prop.PropertyType.Name.StartsWith(nameof(ObservableCollection<string>)) || prop.PropertyType.Name.StartsWith(nameof(List<string>))).ToList().ForEach(prop => ((dynamic)prop.GetValue(this, null))?.Clear()); Although you said that you still had problems after adding the above line, it could be a symptom, but not the cause. You could investigate the memory leak using this:. But as you already identified that just repeatedly calling a page will increase your memory I would focus on that.
You are correct, but it won't be garbage collected immediately, (And depending on some factors it might not even be cleared the next time the GC will collect the memory), It's memory will be reclaimed when the Garbage Collector deems it necessary, which depends on multiple factors that might even be fine-tuned during the running of your program, and it's not something you normally have to worry about. |
I noticed this in your code: this.StatusBarEvent.OnChange -= HandleStatusBarChangedEventAsync; Make sure this is balanced (even amount of adds to remove) as this could potentially lead to memory leaks. |
@MariovanZeist Thanks for the reply, I will follow the steps in the link you provided to see if I can determine exactly what the issue is. I agree with what you are saying in that clearing the collections should not be necessary. If I can come up with anything more specific, I will post back here. For now, I am going to close this issue. |
@gregoryagu the last screenshot in your case isn't telling you much, it just tells you the memory that Page is holding on to, but you want the opposite, you want to know who holds on to this Page. What I would suggest is: You might still have a lot of circular references in that list (A Page holding on to a table holding on to the Page again) these aren't necessarily your problem, as .NET can handle these circular references just fine. But there will be a lot fewer objects to compare so it will be easier to spot the culprit. There is a nice video you could check out here: |
@MariovanZeist Thank you so much for your support. After quite a bit if digging, I have resolved the issue and it is no longer holding onto the pages and the memory leak is no longer occurring. So for now, I am going to let this rest. Again, thanks for providing guidance on resolving this. |
May I ask what was your issue? |
It seemed to be a combination of things, include an event aggregator and using a base class for a page. The code really should not have leaked memory (from what I understand about GC and memory), but it did and through trial and error, we modified the code so that the memory leak no longer occurred. But there was no one single smoking gun. The lesson learned here for me is that memory usage monitoring should be a part of the development flow, not something tacked on at the end after the project is in beta. I wish I had a better explanation, but that's all I've got. :) |
Even so I can understand :)
Thanks
A terça, 25 de jan de 2022, 14:20, Greg Gum ***@***.***>
escreveu:
… It seemed to be a combination of things, include an event aggregator and
using a page class for a page. The code really should not have leaked
memory (from what I understand about GC and memory), but it did and through
trial and error, we modified the code so that the memory leak no longer
occurred. But there was no one single smoking gun. The lesson learned here
for me is that memory usage monitoring should be a part of the development
flow, not something tacked on at the end after the project is in beta. I
wish I had a better explanation, but that's all I've got. :)
—
Reply to this email directly, view it on GitHub
<#39238 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABAVZAZVQAV6UWUTKJJ6L4DUX2WTVANCNFSM5K7AEVXQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you commented.Message ID:
***@***.***>
|
I have a Customer Service app which is used by about 10 staff. It is a .net 6 Blazor Server app. It uses EF Core 6 to retrieve and update data from Sql Server.
The app runs as expected as far as the end user is concerned.. However, what is unexpected is the memory usage on the server. The memory usage continually climbs until about 4 gigs of memory is used by the Application Pool at which point it is automatically recycled due to the settings on IIS for memory usage. In production, this recycling occurs about every two hours throughout the day. (Initially, this setting was not set, and it ate all the memory of the server until the server started throwing out of memory exceptions.)
The question is whether this is expected behavior or not. I have used the Diagnostic Tools in VS22 to see what is happening with the memory. The memory grows each time a page is accessed within the application. If the user stays on the same page, the memory stays level. But if that page is left, and then the user comes back to the page again, the memory raises, never to come back down again.
When the page is initialized, there are various lookup lists that are populated. For example, there is a list of Contacts with about 75 items. If I go to this page, and then take a memory snapshot, then I can see the count at 75 Contacts. If I then leave the page and go to a different page, and then come back again, the same list is again retrieved from the database, and in memory, there are now 150. The count grows every time the page is accessed.
It seems to me that the GC would be collecting these no longer used Contacts. But even if a force a GC with GC.Collect(), there is no reduction in the number of items.
So is this expected behavior? If not, what should I be doing to clean up these resources?
One thing I have found to help is that if I clear the Collection in the Dispose() method of the page, then these objects do NOT show up in the Heap, and after a GC, the memory is reclaimed.
For example, after going to the page 20 times without using List.Clear(), the heap size even after a GC is 41 Megs.
Using List.Clear() in the dispose() for 20 page views results in the heap size of 41, but after GC, it drops down to 23 Megs. So clearly this is beneficial. But as I understand garbage collection, the object which are no longer used in a page should be automatically cleaned up. Is this concept incorrect?
The text was updated successfully, but these errors were encountered: