WPF Memory Usage

2019-03-19 03:59发布

问题:

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?

回答1:

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.



回答2:

LOL 200MB startup and 1GB run.. More common penalty on x64 (and you will need it for bloat) is a penalty of around 64MB for startup and another 120MB for semi-advanced functionality, which is still huge and of course GC will keep adding more.

That's gotta kill the CPU and all the periphery around it in no time. Now imagine everything runs on that, all apps, and the entire OS and stack (as VS2010 surely will attempt some move in that direction).

I'd say: welcome to the modern way of bloatware mania and its ease of accessibility. No matter what you do you'll spend more time finding workarounds then following some 'universal' framework to quick and cool and well-styled and customisable apps. Sure WPF is good on paper but a waste of resource in any practical use (tons of resources and a steep learning curve).

And they said it was and still is the future (same for JDK apps which are oh-so-widespread).

Simply N.U.T.S + the most excellent example that it is not about speed (as CLR defenders will jump in with trivial examples) of managed code. It is about huge scalability impairement and machine wipeout as with every single GC and object-root environment out there.

Vote down coming.. go on disciples, you know you want to.

(and write to Obama against CO2 reduction that will not happen; perhaps multiply by 1003120x if that bandwagon keeps going the way it has. Even a Cray Jaguar wouldn't run that kind of operating environment any time in the next 20 years ).



回答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



回答4:

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.



回答5:

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.



回答6:

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.