I am noticing large amounts of this class being leaked in our automated environment. I tried to search around for this issue but am not finding any available information.
ANTS says that all these instances are GC root objects.
As far as I understand, HwndSubclass is used by the WindowsFormsHost. However, in this particular scenario WindowsFormsHost is not used. This is confirmed by ANTS, which has no knowledge about any instances of WindowsFormsHost.
In what other circumstances is HwndSubclass used and how can I make sure that it gets cleaned out properly?
EDIT:
Just to make sure... the environment is WPF4 (x86) on Win7 (x64).
Looks like it's "by design".
From comments in the HwndSubclass code:
// Allocate a GC handle so that we won't be collected, even if all
// references to us get released. This is because a component outside
// of the managed code (ie. the window we are subclassing) still holds
// a reference to us - just not a reference that the GC recognizes.
and then
// This is LIVE OBJECT because it has a GCHandle. The only time LIVE OBJECTS
// are destroyed is during Shutdown. But Shutdown cleanup is handled through
// the ManagedWndProcTracker and hence no work needs to happen here. PLEASE
// NOTE that reintroducing any cleanup logic in here will conflict with the cleanup
// logic in ManagedWndProcTracker and hence must be avoided. If this instance
// has been disposed its GCHandle is released at the time and hence this object
// is available for GC thereafter. Even in that case since all the cleanup has been
// done during dispose there is no further cleanup required.
Related
Hi I created a window in wpf.
It is a Print preview screen.
It displays (FixedDocumentSequence) in DocumentViewer.
FixedDocumentSequence was created by Flow Document with dynamic binding.
single window occupy nearly 500MB.
Every time memory leaks about 100MB.
If opens more than 5 or 10 times memory overflow 1GB.
I opens window in STA thread(not UI thread). Execute Dispatcher shutdown method. But some objects not release from memory.(after dispatcher shutdown memory object still alive?)
I have used WinDbg to check memory leak, the Flow document section still displays.
!dumpheap -stat
I check the root of the object. But it shows “Found 0 unique roots”
!gcroot [address]
My English may be poor to understand the meaning of the question.
[Question No.1] Could you please give me any suggestions to solve the memory leaks.
(Another one information and question:
I want try to set null too in dispose method.
GC finalizer call the destructor from another thread.
so run time can’t saw the object value and can’t set the value to null in dispose method.
[Question No.2] I already shutdown the dispatcher. So is it necessary to implement anything in Dispose(bool disposing) method?)
Every time memory leaks about 100MB.
Actually that's great. Memory leaks that are reproducible should be easy to fix.
I opens window in STA thread(not UI thread).
I don't understand. If you use Application.Run(), that thread will become a UI thread.
I check the root of the object.
Which object? And why did you choose it?
But it shows “Found 0 unique roots”
That means it's eligible for garbage collection. Next time the garbage collector runs, it will likely be gone.
I want try to set null too in dispose method.
For the object that is reported as "Found 0 unique roots", that has already been done.
But even if you set all variables to null, the objects will still be there. You just don't have a reference any more.
GC finalizer call the destructor from another thread.
That's normal. There is a dedicated finalizer thread.
so run time can’t saw the object value and can’t set the value to null in dispose method.
You can set variables to null inside the finalizer thread. Memory can be accessed from all threads.
So is it necessary to implement anything in Dispose(bool disposing) method?)
Without knowing what resources your window uses, that's hard to tell.
How to procede?
First, get a better tool than WinDbg. It can be done with WinDbg, but it's a lot of effort. No matter what tool you use:
Run the leaky application
Reproduce the leak
Force a garbage collection (implement a button if you can't do otherwise)
Take a snapshot (basically that's a full !dumpheap)
Reproduce the leak again 7 times if possible (otherwise 5 or 3 times)
Force a garbage collection again
Take a snapshot again
Compare the two snapshots (create a diff)
In the snapshot diff, you can now look for new objects that have a multiple of 7 (like 21, 70, 91, ...). These are the ones that leaked. Check the GC roots of those.
It's quite unlikely to leak 5, 6, 8 or 9 objects when you reproduce the leak 7 times. I choose a prime or at least odd number, because multiples of 2, 4 and 8 occur naturally in computer programs.
Doing the diff with the output of !dumpheap in WinDbg is hard. You probably need a .logopen to capture all output. And maybe you end up writing your own parser for the logfile then.
I see a lot of developers use Jetbrains Resharper. Some licenses include dotMemory. I'm quite happy with it, it gets the job done.
In my Tcl extension, a secondary thread is filling the Tcl event queue with events; the events contain pointers to structures with a dynamic life time.
What is the right strategy for ensuring that no events with dangling pointers to de-allocated structures remain in the event queue? I can prevent the secondary thread from creating new events; currently I call Tcl_DoOneEvent(TCL_DONTWAIT) in a loop till it returns 0 (i.e., event queue is empty) after ensuring no new events can be created and before de-allocating the structure.
Is that the right way to do it?
On a related note, I am unsure of the purpose of Tcl_ThreadAlert(): if this is needed after every call to Tcl_ThreadQueueEvent(), why isn't the alert included in Tcl_ThreadQueueEvent()?
Finally, my code does not call Tcl_CreateEventSource(), since it doesn't seem to be needing a setup nor a check procedure as a second thread is involved. Is that cause for concern?
On the first point, that seems OK to me. It is very much like running update at the TCL level.
I'm not sure about the second point, as it isn't part of the API that I have explored a lot. It might be that way to allow multiple events to be scheduled per notification, or because there are other uses for the call, but I really don't know.
On the third point, it sounds fine. I think you never need special event sources just to do inter-thread messaging.
I have a Observable.Timer(TimeSpan) multiple times, but in couple of places I have used Observable.Timer(DateTimeOffset) to trigger the event at that time, but I believe it is stopping my process from exiting.
DateTimeOffset offset = new DateTimeOffset(minStart);
Observable.Timer(offset)
.Subscribe(_ =>
{
UpdateActive();
});
This piece of code is in my ViewModel and on Window Closed, the process is still running in the background, normally wherever I use the Observable.Timer(TimeSpan) they gets disposed automatically, why doesn't this?
Am I doing something wrong or is it a bug? Or am I missing something?
Given that you're using one of the Subscribe() extension methods, assuming you're using a recent version of RX, the observable should be releasing any subscribers when it completes. Is your observable completing in one case but not the other?
If your observable has not completed (i.e. if the time represented by offset hasn't happened yet) by the time you close your window, nothing is going to automatically unsubscribe for you. Here's what the introtorx site has to say on this matter (emphasis mine):
Considering this, I thought it was prudent to note that subscriptions
will not be automatically disposed of. You can safely assume that the
instance of IDisposable that is returned to you does not have a
finalizer and will not be collected when it goes out of scope. If you
call a Subscribe method and ignore the return value, you have lost
your only handle to unsubscribe. The subscription will still exist,
and you have effectively lost access to this resource, which could
result in leaking memory and running unwanted processes.
Using the overload of Observable.Timer that accepts DateTimeOffset will not on it's own cause a process to be held open; something else is responsible for this.
However, the consequence of not disposing subscriptions to Observable.Timer is that you will leak the timer resource.
You should retain the IDisposable subscription handles for timer and event based observables and dispose them appropriately; most WPF frameworks provide a suitable event for this.
In general, I track and dispose of all my window-scoped subscriptions, just to be on the safe side. See Convert Polling Web Service to RX for an example.
Basically I'm working on a program that processes a lot of large video and image files, and I'm struggling with the memory management side of it because I've never dealt with anything quite like this before.
For instance, it stores all these images in a database, and loads a list of videos, and then you can switch between the videos and view images from the video. Right now, it's keeping all of those images in memory all the time, which is eating up a lot of space. I know I can lazy load the images, but once you've switched back and forth you get all of them stuck in memory.
I want to take advantage of the WPF databinding functionality and MVVM as much as possible, but if I need to look at a different architecture I will.
I'm just looking for general advice, tips, links to articles, or anything that could help.
One of the things you could look at is data virtualization, which is not provided in WPF by default (they provide UI virtualization instead). Data virtualization can say 'load and bind the data for an item / range of items while visible, then unload when not visible'.
Here's a great article that describes a concrete implementation that you may be able to use as-is or adapt:
http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx
It sounds like the main problem you're having is not so much the performance-intensiveness of the application (which things like fixed-size buffers and static allocation will help with) but its overall memory footprint. The way to control that is with virtualization.
Lazy loading gets you halfway there: you don't actually create the object until something needs it. That's fine, but the longer the user works with the application and the more objects he visits in the UI, the more objects get created, and eventually the application runs out of memory.
So you want to throw away objects that the user doesn't need anymore. Figuring out which objects the user doesn't need can be a hard problem, but it can also be as easy as assuming that the user doesn't need the object that he used least recently. You use a least-recently-used (LRU) cache to do this.
This is totally consistent with the MVVM pattern. In your view class, you make your property getter for the object use this pseudocode:
if object hasn't been loaded
load object
add object to the LRU cache (whether you loaded it or not)
return object
The LRU cache I wrote keeps a simple queue of the objects it contains. When you add an object to the cache, if it's not already in the queue it gets added to the back, and if it is already in the queue it gets moved to the back.
If the queue's at its capacity when you add an object, it pops off whatever is at the front of the queue (which is the one that was used least recently) and raises the DiscardingOldestItem event.
This event is the object's chance to tell anything that holds a reference to it (i.e. the view object that it's a property of) that it needs to be discarded (probably by raising an event of its own). The view object's event handler should first raise the PropertyChanged event. If the property getter gets called when it does this, there's a binding somewhere that's still looking at the property, so it shouldn't be discarded yet. (Also, since the getter was called, the object just got moved to the back of the queue.) Otherwise, it can be thrown away.
(Note that if you have more objects visible in the UI than the cache can hold, this little dance becomes an infinite loop and you'll get a stack overflow.)
A more sophisticated approach would have the LRU cache start discarding old items when the application started running low on memory (it uses a fixed capacity right now). That's a straightforward change, but if you make that change, the scenario described in the previous paragraph is something you need to give more thought to; one very large object could result in the whole UI going kablooey.
It seems that to increase raw performance you would actually want to avoid patterns. They have their uses, don't get me wrong, but if you're trying to blast video at the highest performance possible the last thing you need to do it introduce abstraction layers that are designed to write higher quality code, not increase application performance.
this article on informIt has a lot of good info on the subject although it is more c and c++.
Static Allocation Pattern: Allocates memory up front
It suggests,
Pool Allocation Pattern: Preallocates pools of needed objects
Fixed Sized Buffer Pattern: Allocates memory in same-sized blocks
Smart Pointer Pattern: Makes pointers reliable
Garbage Collection Pattern: Automatically reclaims lost memory
Garbage Compactor Pattern: Automatically defragments and reclaims memory
"I know I can lazy load the images,
but once you've switched back and
forth you get all of them stuck in
memory."
This is not true to my understanding. The images can get garbage collected just like anything else, by removing all references. Are you sure you dont have a reference to them somewhere? Try a memory profiler like memprofiler or ANTS to see whats happening.
To those who have found this question looking for general patterns (not WPF) to reduce memory, the famous one (which I have never seen used!) is The Flyweight pattern
This is an odd one. I am making a app that is kind of a game, and I wanted to have a shooting starburst effect. I made it one evening and it all worked well, until I noticed that my browser was eating over 300 megs of ram, eating 1 meg every 5 seconds, mainly when the starburst would happen.
Here is an example stripped down to just the starburst:
http://www.sizzln.com/example.htm
First thought, I am not removing the objects or still have references somewhere. I am placing each generated star into a Canvas, but I am removing old starts every 3 seconds. I do have a lot of DoubleAnimations as well, but I even have a callback to set everything to null.
Here is the weird part, if I convert it to WPF it doesnt happen, if I run it inside of Silverlight Spy 3, it doenst happen. If I take a Heap Dump using WinDbg and SOS.dll, it reports that it should only be using between 1.8 and 3 MBs of ram.
I have the GC running every 3 seconds to cleanup, but it never has any effect. I can see in the heapdump that many objects are now deleted, and I always get back to 1.8 meg or so after a GC, but the memory shown in Task Manager just keeps going up.
I dont know what to do, I think I am carefully removing the objects unless my Heap is not being honest.
Are you running Vista or Win7? It sounds like the OS is not reclaiming memory, as it shouldn't unless it needs to.
It may also be that the Silverlight GC doesn't free its buffers, on the assumption that the memory may need to be reallocated soon.
In either case, it doesn't sound like anything to worry about, as long as the profiler says your program only uses 1.8MB after the GC runs.
I just briefly looked over your code. You have a lot of places where you hook into events (+=), but never unhook (-=). These are hard references and therefore won't ever be collected if they are ultimately connected to a root object.
OK I am going to sorta answer my own question. Silveright doesn't have the handy "BeginAnimation" method, so I found online a quick way to add an extension to do basically the same thing, it did this by creating a storyboard and starting it.
However, it just stayed there, I dont exactly know what it was being connected to either. Calling Stop() on it after it finishes fixed my memory issue.
One odd side effect is I have to be careful when I call the stop method, when creating so many storyboards it seemed to get a bit confused and it would cause some of the objects to reappear, even after they were removed from the control.