XamlAnimatedGif / WpfAnimatedGif

A simple library to display animated GIF images in WPF, usable in XAML or in code.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Memory Release Problem (2)

Podpivasnique opened this issue · comments

Hello there, I have a trouble with memory release. I have a few bitmap (gif) which i initializate in my wpf window constructor like in your documentation:

_gif1 = new BitmapImage();
_gif1.BeginInit();
_gif1.UriSource = new Uri("pack://application:,,,/Images/1.gif");
_gif1.EndInit();
_gif2 ...

And on button click i play the gif - ImageBehavior.SetAnimatedSource(ImageControl, _gif1);
The problem comes when i try to play another gif in image control (ImageBehavior.SetAnimatedSource(ImageControl, _gif2);) - memory starting to leak. It seems just previous gif didn't disposed or something like that. I saw this #75 (comment). I tried to ImageBehavior.SetAnimatedSource(ImageControl, null); and also tried call GC.Collect(2, GCCollectionMode.Forced); but it didn't help.

Also, sorry for offtop: Can I somehow play gif from the end till start?

Hi @Podpivasnique,

Sorry you're having trouble. How do you observe the memory leak? Task manager? Profiler? Does the app crash with OutOfMemoryException?
Are you able to reproduce the problem in a minimal app?

Can I somehow play gif from the end till start?

You could, using ImageAnimationController.GoToFrame, but you would need to handle the timing yourself. There's no built-in way to play an animation in reverse.

How do you observe the memory leak?

First time I saw this in task manager. So, I took a profiler snapshots:
1 - before gif usage.
изображение
2 - first gif
изображение
3 - second gif
изображение

OutOfMemoryException

No (not yet), but it's still critical for me becasue my project in .net framework 4.0 and I need windows XP old pc's support. And for this reason I unable to use Win2D or XamlAnimatedGif.

Are you able to reproduce the problem in a minimal app?

It's already kind of a minimal app - few buttons, image control, few textblock, background and entity dbContext only once opened (and closed), nothing else.

OK, so it looks like a real leak. I'll look into it

It's already kind of a minimal app - few buttons, image control, few textblock, background and entity dbContext only once opened (and closed), nothing else.

Any chance you could share it with me (maybe without the DbContext part) so that I can reproduce the problem?

I created minimal app https://github.com/Podpivasnique/WpfAnimatedGifTestApp which represent my current project.
So, it's actually disposing, but too late. It's disposing on first gif (in new circle), on fourth gif memory leak comes to 1.4gb.

Thanks @Podpivasnique, I'm looking into it now.
So far I just looked with Task Manager; I see the memory usage go pretty high (above 1GB), but it goes down every now and then and doesn't seem to grow farther than that.

If I keep switching between images, memory usage never goes over 1.4 GB, and often falls back to 500 or 600 MB.
Using the VS memory profiler, I'm unable to identify any object that the library holds onto after unloading an image. There are a few low-level WPF internals that stay in memory for a while, but they seem to get collected after a while.

So, it uses an awful lot of memory (which is a well-known problem of this library), but I don't think there's a leak...

The fundamental problem, I think, is that your images are very large (e.g. 1.gif is 1200x700, with 29 frames), even though they are very poor quality. Keep in mind that WpfAnimatedGif holds all the decompressed frames in memory, so using such large images is bound to use a lot of RAM. In this case, you could probably make the images much smaller without losing quality, and just scale them up if you need to make them look larger. E.g. if you resize them down by a factor of 5, pixel data would use 25x less memory...

As for why the memory isn't immediately reclaimed when you GC.Collect, I suspect WPF does its own management of low-level primitives, and unfortunately there's no way to control that, as far as I can tell.

it uses an awful lot of memory (which is a well-known problem of this library)

I know.

I don't think there's a leak

I was tested that minimal app on clear virtual win xp with 1gb ram and application crashes on third gif, but the gif actually pretty similar and on first-second gif the process uses 400-500mb. That's why I wrote about too late disposing - I thot there is a way somehow align memory only for current gif.

WPF does its own management of low-level primitives, and unfortunately there's no way to control that

Eh, sounds bad man.

if you resize them down by a factor of 5, pixel data would use 25x less memory

Sounds interesting. Can you tell in more detail how can I do this (in which application)? Because I haven't really work with images/gifs. Gifs in project I was created here https://ezgif.com/ , and I have all original raw frames.

Anyway, thanks for your supporting.

Can you tell in more detail how can I do this (in which application)?

Not really... I guess there must be applications capable of resizing animated GIFs, but I don't know them.

Gifs in project I was created here https://ezgif.com/ , and I have all original raw frames.

in this case you can resize the original frames and recreate the GIFs

But I think you would get better results (in terms of performance and memory usage) with a video instead of an animated GIF

I think you would get better results (in terms of performance and memory usage) with a video instead of an animated GIF

Can you recommend .net framework 4.0 wpf video library?

Can you recommend .net framework 4.0 wpf video library?

Not really... What's wrong with the built-in WPF video support? (MediaElement control)

What's wrong with the built-in WPF video support? (MediaElement control)

Nothing, I just didn't knew about it.
So, I just converted gifs into avi and use MediaElement, thank you.