views:

695

answers:

2

I've asked a question about my memory management problem in WPF, but this is a different one about the same problem. I am using DotTrace trying to figure out what's going on. When I start up my app, I can see in Task Manager that it is taking 200MB. DotTrace says a total of 33MB. If I simply minimize the window and bring it back up, the memory footprint according to TM is about 25MB.

I have a ListBox that shows peoples names and pictures. It shows up to 3000 people (I will work on paging, but that's not the point here). As I scroll down, I can see in TM that the memory increases rapidly. If I just keep scrolling up and down memory quick gets to 1GB. During the scroll there are no changes to the underlying data and there are no events of my own. If I minimize the window and bring it back up, memory drops from 1GB to 25MB.

Before minimizing and seeing the memory go down in TM I took a snapshot with DotTrace and it shows the same amount of memory as before the scrolling - around 30MB or so.

Can someone please explain to me what happens to memory when the app is minimized? Is the figure shown in Task Manager to be trusted?

Thanks

PS1: There's no change in behavior if I do or don't add this to my ListBox:

VirtualizingStackPanel.IsVirtualizing="True" 
VirtualizingStackPanel.VirtualizationMode="Recycling"

PS2: I've put a button with the code, and the GC doesn't reclaim much if anything(it drops from, say 700MB to 680MB):

    GC.Collect();
    GC.WaitForPendingFinalizers();
A: 

If you are using a Virtualizing container, the visual objects will be created dynamically as you scroll around. This will in turn could cause a bit of havok with the GC since you are creating rather chunky objects very quickly. Once you minimize, I would assume that the GC is kicking in and collecting all those visual objects.

EDIT:

After seeing your edit, you might want to try setting the IsVirtualizing to false for testing. The default value is true, so omitting it would not change anything.

Erich Mirabal
Erich, thanks for your comment. So how can I fire off the GC in the same way it happens when minimizing occurs? I have done this without any improvement: GC.Collect(); GC.WaitForPendingFinalizers();(added this to question)
Gustavo Cavalcanti
With IsVirtualizing = false all the controls for all the data are created and the amount of memory in Task Manager is 1.1GB
Gustavo Cavalcanti
Oh, and 1.1GB later, if I keep scrolling up and down, memory keeps going up rapidly.
Gustavo Cavalcanti
Umm... long shot, but have you tried 'invalidating' the control? Maybe forcing a re-render might induce the same kind of clean-up.
Erich Mirabal
It makes sense that with virtualizing off it would use 1.1 GB (assuming that's your "max" usage). It does NOT make much sense for that to keep growing since it should be done allocating and creating visual. Sounds like there are some other issues at hand.
Erich Mirabal
Yeah, it grows, but not as rapidly, I must say. And when I fire the GC manually memory is actually reduced to 1.1GB.
Gustavo Cavalcanti
One other note on this is that when I see 1.1GB in Task Manager, if I take a memory dump with DotTrace, it shows a total of 121MB. Where is this bloating in TM coming from?
Gustavo Cavalcanti
Here are some numbers:At start up: Task Manager=210MB, dotTrace=32MB, Working Set Analyzer=197MBAfter minimizing:Task Manager=54MB, dotTrace=32MB, Working Set Analyzer=46MB
Gustavo Cavalcanti
+1  A: 

Can't give you a definitive answer, but some things to point out:

  1. DotTrace only shows managed memory usage. It looks your app is using large amounts of unmanaged memory (possibly allocated by WPF itself for all those images).

  2. Minimizing a process doesn't generally free any memory, it just pages it out so it can be used by other applications. It's a red herring in this case.

  3. Look into how .Net's generational garbage collection works.

  4. Until your process reaches the resource limits set by the OS it will not necessarily release any memory it has allocated to it.

  5. Use the Performance Counters built into Windows. They will show you a more useful overall breakdown of your app's memory than DotTrace, including managed and unmanaged memory.

  6. DotTrace sucks. Get ANTS or something. I love ReSharper, but Jetbrains really shouldn't charge for DotTrace, it's woeful.

Edit: 4) is a bit misleading - .Net's memory manager can release memory for other reasons (when a generation is full, for starters).

Jim Arnold
DotTrace has a good performance profiler, but I agree the memory profiler is woeful.
Cameron MacFarland