I am working on a WPF application which doesnot seem to release all the memory when logged out of a screen. On start of app, there is a login screen where I enter userID/Pwd. It takes to a different screen(lets say WPF2). At this point, I am totally unloading the login screen(memory now is 70MB). WHen the WPF2 screen is loaded with dynamically memory goes upto 200MB. When the user logs out from WPF2, login screen loads again. AT this point, I am clearing all objects used in WPF2 in dispose method. But the memory is still 200MB not 70MB, and also when I login again it increases from there.
WHen the application is closed, all memory used is released.
I understand this is very application specific question, but any general ideas are highly appreciated.
Thanks
Items are not released from memory when an event handler is still attached to them, or when the application closes.
This sounds like you have some event handlers to clean up.
Hope this Helps,
You gave not enough information about how you get the memory values. I assume you looked in task manager? If you look only at task manager, you will probably not get the values you expect. Furthermore, memory releasing is not done in the moment a object is no more used. It is an asynchronous task done by the Garbage Collection. If you want to measure memory at a specific point of time, you probably should force GC to free memory before (but only for measurement, not for production code). Look at this thread to get a starting point about the different memory types.
Here you find a very good video, that gives a start to debug memory problems in WPF.
When you call Dispose()on a IDisposableyou can clear umanaged resources.
The GarbageCollector may not have collected WPF2 yet.
Related
I needed to write an application for kiosk terminal and I choose WPF for this, because I need single window application. Implementation is simple - NavigationWindow and set of Pages, that uses in NavigationService.Navigate() method.
During using the application, I saw that it freezes, consuming large amount of memory. I found that when content is navigated to, NavigationService records the navigation as an entry in navigation history. I started to clean up history by using NavigationService.RemoveBackEntry() method.
Yes - history is cleared, but page's finallizers doesn't call. Pages are still being in memory and finallizers call only when the application is closed. I can just go from one page to another and then go back several times - application will consume about 150-200 Mb (starts from 5-6 Mb).
I checked the application with memory profiler and found that used memory doesn't increased - its about 5-8 Mb, but working set consume large amount of memory.
So I found a way to clear working set, but I didn't leave a thought that it is a wrong way. Solution must be more easier.
Documentation says that NavigationService does not store an instance of a content object in navigation history. Instead, NavigationService creates a new instance of the content object each time it is navigated to by using navigation history. This behavior is designed to avoid excessive memory consumption. But as I see it doesn't work this way.
I was thought that this behavior works only when NavigationService use URI for navigation (I call Navigate(new MyPage()) for navigating), but is doesn't work even with URI - pages instances still being in memory even if I clear the history journal.
So here is the questions:
1) Anyone else faced a similar problem?
2) Is that correct and best way to use NavigationWindow to build a single-window application?
On GAE my handler calls a function that does all the heavy lifting. All the objects are created within the function. However after the function exits (which returns a string for response.out.write) the memory usage does not go down. The first http call to GAE works, but memory stays at about 100MBs afterwards. The second access attempt fails because private memory limit is reached.
I have cleared all class static objects that I wrote and called the close and clear functions of the third party library to no avail. How does one cleanly release memory? I'd rather force a restart than tracking down memory leaks. Performance is not an issue here.
I know that it is not due to GC. GAE reports that memory stays at high level for a long period of time. The two http calls above were separated by minutes or longer.
I've tried to do the import of my function in the Handler.get function. After serving the page I tried to del all imported third party modules and then my own module. In theory now each call should get a restart of all suspected modules but memory problem still persists. The only (intended) modules left between calls should be standard library modules (including lxml, xml etc).
EDIT:
I now use taskqueue to schedule the heavy duty part on a backend instance and use db.Blob to pass around the results. Getting backends to work solves the memory issue. GAE documentation on backends is complete but confusing. The key is that one needs to follow the instructions on 1) editing backends.yaml 2) using appcfg to update (deploying from launcher is not enough). Afterwards check in admin that the backends is up. Also taskqueue target= breaks on the development server so one needs to work around it on the development server.
This is (probably) due to the fact that there is nothing saying that the garbage collector (which is in charge of freeing unused memory) will kick in directly when your function returns.
You could manually force it to kick in via a few hacks but that will not solve anything if two http request happens aprox. at the same time.
Instead I recommend you to look over solutions which doesn't require you to do the heavy lifting on each request.
If the data generated is unique for each request see if you can do the computations outside of your (limited) private memory pool.
how do I manually start the Garbage Collector?
When your heavy weight variables have gone out of scope invoke the GC by using the below method.
import gc
...
gc.collect ()
I've an application written in VC++ MFC 6.0. Recently got upgraded to .NET 3.5 by compiling in vs2008 and added some WPF applications to it by using managed and unmanaged environment. Basically hosting WPF on win32 window. If I just open a WPF app window, memory keeps going up like 1KB/10 secs. I've tried using .NET Memory profiler & Ants memory profiler. But both are not helping me in detecting the leaks!! I've removed all the WPF controls from the hosted WPF application. It just contains a page having just a frame. But still the leak happens!! Would some one please help me what could cause the application memory go up?
First, you should determine whether you have a managed memory leak or a native memory leak:
Use these PerfMon counters to do that:
Process/Private Bytes,
.NET CLR Memory/# Bytes in All Heaps,
.NET CLR LocksAndThreads/# of current logical Threads.
If 1 is increasing, but 2 remains stable, you have a native memory leak.
If 1 AND 2 are increasing, you have a managed memory leak.
If 3 is increasing unexpectedly, thread stacks are leaking.
If you have found a managed memory leak, .NET memory profiler tools like Ants, YourKit, etc. should help. Since they did not help in your case, you probably have a native leak.
Important: make sure to invoke the garbage collector manually before looking at the memory consumption. If there is not enough memory pressure, the GC will not run and your process' memory increases (which is not a leak in this particular case.) Invoke GC like this:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
This article describes some common causes of memory problems with WPF - may be worth taking a read:
http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/learning-memory-management/WPF-Silverlight-pitfalls
Regarding your attempts to find the leak with memory profilers, try the following with ANTS:
1) Take two snapshots a minute or two apart (the profiler automatically runs a garbage collection prior to taking the snapshot each time).
2) Ensure the baseline snapshot is set to snapshot 1 and the last snapshot is set to snapshot 2.
3) Go to the class list.
4) Under 'Basic filters' select 'From current snapshot show only new objects'.
5) Highlight the largest class then go to the instance list.
6) For one of the instance, open the instance retention graph which shows the chains of reference holding that instance in memory.
7) With a bit of luck, you'll see an object holding onto something it shouldn't which you can then fix. If not, repeat steps 5 & 6 but selecting different classes / instances.
Well, after some soul searching, found out that the leak is actually due to a bug in the framework.
Read this for more
http://social.msdn.microsoft.com/Forums/zh/wpf/thread/5b9ae245-9067-4ca4-b846-180db9f7bde5
My silverlight application has many pages and uses Navigation Service to navigate between pages. One of the pages fetches a large amount (~1G) of data from a web service. Since garbage collection is not happening automatically, I need to clear the memory allocated in that page when I go back to the previous page (Home page).
I tried overriding OnNavigatedFrom method and tried assigning object references to null and forcing a garbage collection by GC.Collect(). But the memory is not getting cleared. I noticed that if I refresh the Home Page, the memory comes down drastically. How to do memory clearance programatically.
Calling CG.Collect manually is not a good idea, and in any case GC.Collect does not help removing memory leak. Memory that can be free is free by the standard CG behaviour. Maybe looking for the reason that memory is not automatically free will evidentiate some bug somewhere.
You will need to spend a lot of time tracking the memory leak down and this can be a painful process. There are some good tools out there that can assist you.
See my previous post here: Silverlight 4 memory leaks
One way I've cleared the memory is to re-load the page, or to have the same app span across multiple asp.net pages...
So instead of navigating, it will unload the app (releasing all memory) and re-load the app. I know gurus will hate this short-sighted answer, but it's the only way I've effectively been able to have the memory dump.
An example would be say your app is in default.aspx and instead of navigating to something like default.aspx#control1, you put the same app in a new page like control1.aspx and navigate to control1.aspx#control1. Either that, or you can separate the app out into multiple apps to be loaded across multiple pages.
I've noticed huge gains from this.
In the old days for WinForms, if your user was creating/editing some information in a DialogBox, it was easy to detect the Window closing and if the data was dirty, ask if they wanted to save.
My question is, how do you approach this scenario in Silverlight where everything seems to be done in UserControls, which have no obvious way of knowing when the page is closing, ie switching to another page within the Silverlight app would simply open a different UserControl without checking the previous UserControl needed saving.
There must be some standard way of achieving this?
If you need to ask the user a question about whether to save or not then you will need to handle this in the browser the onbeforeunload (whilst not a standard event it is supported by those browsers on which Silverlight is officially supported). It may be possible to set up a little javascript to call back into your application when onbeforeunload fires.
That said I'm not a fan of the "Are you sure, you want to lose all that work you've just done" type of question. "Of course I don't want lose it, save it already, as long as I can undo it later if necessary I'm happy".
You can handle the Application.Exit event to execute code on application shut down. Be warned that at this time the networking stack has already shut down so you can't send any messages from the Application.Exit. You cannot cancel the event.
+1 Michael. It is a current limitation of SL. You can however persist to isolated storage from the app exit event, would it be feasible in your app to check if dirty, and if so save to iso storage. Then next time your app loads you could load the dirty data from iso storage ready to carry on editing..?