XamlAnimatedGif / XamlAnimatedGif

A simple library to display animated GIF images in WPF apps (.NET Framework 4.5, .NET Core 3.1, .NET 5.0)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When using XamlAnimatedGif to display online GIF images, the CPU resources are over-utilized.

qian-o opened this issue · comments

A lag occurs when multiple network resources are played simultaneously.
CPU : 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
RAM : 16.0 GB
GPU : RTX 3060 6G
JS`ZMT@V0F_6JILG77JU(DL

URI : http://47.96.133.119/api/Attachment/GetAttachments/eIfN3z27yS_xNPXPhTRee.gif

Hi @qian-o,

Yes, I'm aware that this library has performance issues. It's a tradeoff between memory usage and CPU usage. This library was designed to reduce memory usage compared to WpfAnimatedGif, but it means doing much more work on the CPU.

The fact that it's a network resource shouldn't have much impact; the file is downloaded locally before playing it.

I have plans to improve performance, but

  1. displaying multiple GIFs, especially large ones, will always be costly in terms of CPU usage
  2. I honestly have no idea when I'll get around to make those improvements. I have little free time, so probably not in the short term.

I tried to compare the performance of web resource and local resource. Under the same image, web resource would occupy more CPU, which is 3 times of that occupied by local resource.
Besides, playing web resource in the XamlAnimatedGif.Demo you gave would also occupy a significant share of CPU.
Local resource:
image

Web resource:
image

@qian-o I'm not seeing this on my machine. The CPU load is about the same when loading the image from a URL or from a local file (but when loading from a URL for the first time there's a delay before the image shows up, due to the image is being downloaded)

After repeated tests, I found that when the GIF generation operation is changed to resource and played in the form of a relative path, there will be very little resource occupation.
If it is played in the form of absolute path such as local resource or network resource, it will have extremely high resource occupation.

Resource:
image

Absolute path:
image

I can't reproduce your results. I tried to compare CPU usage between absolute file path and relative path to a resource, but it doesn't show any significant difference for me. Anyway, the Windows Task Manager isn't a reliable tool for this kind of thing. Many other things can cause spikes in CPU usage.
If your results can't be reproduced on another machine, I'm afraid there's not much I can do...

Thank you for your reply. I will continue to test in different environments.

I tried to write the bytes read by FileStream into MemoryStream to do buffer, which could effectively improve the performance.
FileStream:
image

MemoryStream:
image

I think the FileStream used to read files will affect the performance significantly and MemoryStream should be used to do buffer.

Yes, loading the file in memory could help, however it would also use more RAM, which is an issue for large GIFs...

I hope that you will weigh the frequency of using RAM or IO. If there are too many GIF files, they will have a significant impact on the performance.

Maybe I could make it optional on a case-by-case basis

OK, thank you for your reply.

Actually, I don't think I will implement this in the library itself, because it can easily be done by the user, and handling this to the library would just add unnecessary complexity.
You can just load the GIF in a MemoryStream and pass it to SetSourceStream, like you did in your tests.

If it were a network resource, I would need to cache it locally before using MemoryStream, but I might not be able to do that well.

but I might not be able to do that well.

Why not?

但我可能做不好。

为什么不呢?

Ha-ha. I am afraid that I could not write as good as you expected. I find that if the AnimationBehavior.SourceUri is designated, the deserialization in the RichTextBox could not be displayed normally.
I am now trying to figure out how to run the animation normally after the deserialization of RichTextBox. I think it does not have direct relation with additional attribute. It is because that there is the content which could not be serialized in the Source.
I guess that if the Source attributes of Image are shielded during the process of serialization, it might be used normally.

Actually, this might actually be useful. While it's true that the user could do the memory caching themselves, it means being unable to set the source as a URI. I'll try to add an option to load images in memory in a future version.

Well, I'm looking forward to future releases.

I spent quite a bit of time playing with the idea of working completely in memory; unfortunately, I found no performance difference at all. No difference in CPU usage or rendering time whatsoever.
Anyway, the task manager isn't an appropriate tool for measuring CPU usage of a given application (especially not the global CPU usage metrics; at least look at the usage for the process, otherwise it could be influenced by any other app running on the machine).
If this feature brings no benefit at all, it's not worth doing.