views:

126

answers:

5

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.

+1  A: 

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.

Paul Sasik
Patterns aren't necessarily abstractions or additional layers of slowness. Many of them are simply tried and tested engineering approaches to common problems.
Crashworks
@Crash: Agreed. i was thinking of GOF design patterns. There is a world outside of that book. ;-)
Paul Sasik
+1  A: 

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

runrunraygun
+3  A: 

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

Sam
+3  A: 

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.

Robert Rossney
A: 

"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

Schneider
Of course they could be garbage collected but then I'd have to get rid of my references... I don't want to get rid of the references, they're being used. I want to get rid of the collections those objects reference.
Max Schmeling
what collections are the images referencing? ("those objects" == images?)
Schneider