WPF Memory Usage
Asked Answered
J

5

11

Application:

  • WPF Application consisting of a textbox on top and a listbox below
  • Users type a string in the TextBox to find employees, and search results are displayed in the ListBox
  • ListBox uses DataTemplates to display elements (shows employee name, department, phone and a thumbnail picture.)

Implementation:

  • At application startup I query the database and retrieve all employees and related information to be shown in the ListBox. This is kept in memory the entire time.
  • After application startup, all the searchable data is in memory and searches are virtually instantaneous. All searches are performed on the data already in memory.
  • Search results are displayed in the ListBox using DataTemplates. Thumbnail picture, name, phone, department, etc, are shown in each ListBox item.

Problem:

  • At startup the memory usage is about 200MB.
  • As data is changed in the listbox, either via a new search or a simply scrolling down the listbox, memory consumption increases.
  • When users scroll down the listbox slowly, memory increases faster. As you scroll it up and down memory quickly reaches 1GB.

There are is no code creating controls manually - everything is done via data binding.

Why am I seeing this behavior? What can I do to fix it? Please help!

UPDATE: I figured out that the problem is not a memory leak. The issue here is that the listbox is creating objects to display the images of the employee and is not releasing for the garbage collector after the listboxitem gets out of the window. The CleanUpVirtualizedItem event occurs as I expected but the memory is still not released. Any ideas?

Joaquin answered 8/5, 2009 at 20:16 Comment(3)
Well, actually "istbox is creating objects to display the images of the employee and is not releasing for the garbage collector after the listboxitem gets out of the window" - is a memory leakKrys
This is just semantics and it doesn't make any difference, but when you have an object and that object is holding memory, this is not a memory leak. A leak would be to have the object gone and the memory still allocated, for instance.Joaquin
oh, maybe you're right, but this definition fits probably only unmanaged code. while i've been seeing in the .NET world such examples being definitions of a memory leak.Krys
T
8

At the risk of being glib, you have a memory leak. Why not try a tool like ANTS* to track it down. They have a free trial, I've never used it but it has a good reputation.

*Other profiling tools are available.

If you don't want to get to grips with another tool, you can try something like incrementing a static member every time a class is created and decrementing it every time an instance is disposed. This will help you track down instances that are not be destroyed properly.

Tusche answered 8/5, 2009 at 20:26 Comment(2)
I agree with Noel -- there's not enough information without either some code or some profiling. I have used Scitech's tool before, and it was very effective: memprofiler.com I think they have a free trial, and they also have some videos on their site that show how to use it. (I don't work for them or have any vested interest in them -- I just found it to be a good tool).Draft
I also agree with Noel. Get a profiler like the ANTS profiler and see what's staying alive in memory. You should be able to track it down from there.Udall
C
3

You could use

WPF Performance Suite

Optimizing WPF Application Performance

A similar issue haunts me.. (something like)

At application startup I query the database and retrieve all employees and related information to be shown in the ListBox. This is kept in memory the entire time.

May be you could modify your code to follow WPF: Data Virtualization

Confucius answered 14/5, 2009 at 9:43 Comment(1)
Thanks abmv. Although this doesn't answer my question I will look into the Data Virtualization link you provided. I voted up your answer.Joaquin
K
2

It really seems to be memory leaking. Probably, some of the UI elements in the DataTemplate keep references to other objects that should stay alive even when the UI element is destroyed.

There could be some memory leaks with Image control. Try removing it from the template and see the result. Also, are you subscribing to any events in controls' Loaded events or something like that?

Just some guesses though... As people already said here you might really want to look at your app with performance and memory profilers.

Krys answered 15/5, 2009 at 16:21 Comment(0)
A
0

I've noticed that there are some issues in WPF and .NET 3.5 SP1 w.r.t memory issues in seemingly innocuous situations.

I did find a couple of resources, but I'm not sure they would be helpful to you:

http://blog.ramondeklein.nl/?p=58

That blog post describes a situation whereupon when

  1. A style is defined in the application’s ResourceDictionary.
  2. The style uses a control template that uses media effects (i.e. DropShadowEffect).
  3. The media effect should be referenced using a StaticResource

In a nutshell, I think your solution would be to ensure that any media effects (dropshadow, etc) use static resources.

Alexandretta answered 12/5, 2009 at 18:46 Comment(3)
Thanks Josh. I've seen this article but I believe it doesn't address my problem because a) All access to my resources are through using StaticResource; b) I do not use any bitmap effects and c) styles are defined in the Application's ResourceDcitionary (App.xaml).Joaquin
ah, bummer. Do you know what level the objects are being held in the GC? It obviously thinks there are extant references to the objects. Is it possible that the viewable canvas area is smaller than the actual canvas size, resulting in "off-screen" objects still being updated?Alexandretta
Hi Josh, The size is not a factor because ALL of the objects are still being held. When I create the BitmapImage, if I use myBitmap.CacheOption = BitmapCacheOption.OnLoad then all images are created and I end up with 1GB of memory taken. If I don't cache, I start the app with around 200MB but as I keep scrolling, memory increases up to 1GB.Joaquin
J
0

One thing that helped me a lot was to use a class wrapping the Stream class. This is explained in detail here and sure enough I saved a lot of memory by using this method. WPF really keeps the reference to the underlying byte[] and stream for each picture.

Joaquin answered 21/5, 2009 at 20:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.