Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak when using MagickImage constructor with Stream argument for large WebP image. #1163

Closed
REC-James opened this issue Mar 15, 2022 · 6 comments
Milestone

Comments

@REC-James
Copy link

Magick.NET version

10.1.0

Environment (Operating system, version and so on)

Windows 11

Description

Hi. I think I've found a memory leak specifically in the MagickImage constructor that takes a Stream argument.

When loading a 6MB animated WebP image using the MagickImage class, I've noticed that the large memory usage used during the loading does not clear itself after the Using block. This only happens when using the constructor that takes a Stream argument, the other constructors seem to work fine. (I understand that Magick.NET loads in the image as uncompressed pixel data, so the initial memory usage is high, but it clears after the object is disposed normally.) Shown below I have two sets of code to demonstrate the problem.

I can provide a large animated WebP file if you need, but I will have to edit it to take out our customer's specific information first.

Steps to Reproduce

This code shows that the memory after loading the image is released correctly when using the file path constructor. If you look at the memory usage in the Task Manager once it is at the ReadLine() line, it will be low.

using System;
using ImageMagick;

namespace WebPMemLeak
{
    class Program
    {
        static void Main(string[] args)
        {
            const string IMAGE_PATH = "test.webp";

            using (MagickImage image = new MagickImage(IMAGE_PATH))
            {
                Console.WriteLine("Image loaded");
            }
            Console.WriteLine("Note the memory usage in the Task Manager, it is low.");
            Console.ReadLine();
        }
    }
}

This code shows that the memory after loading the image is still high when using the Stream constructor. If you look at the memory usage in the Task Manager once it is at the ReadLine() line, it will be high. Note that the file stream is closed properly with a Using block.

using System;
using ImageMagick;

namespace WebPMemLeak
{
    class Program
    {
        static void Main(string[] args)
        {
            const string IMAGE_PATH = "test.webp";

            using (System.IO.FileStream fs = new System.IO.FileStream(IMAGE_PATH, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                using (MagickImage image = new MagickImage(fs))
                {
                    Console.WriteLine("Image loaded");
                }
            }
            Console.WriteLine("Note the memory usage in the Task Manager, it is high.");
            Console.ReadLine();
        }
    }
}
@dlemstra
Copy link
Owner

This is a symptom of a non-deterministic GC. The GC does not make any guarantees at all about when memory will be freed. This is normal, expected and wanted behavior. When you put this inside a for loop and run it multiple times you will probably see a different behavior.

@REC-James
Copy link
Author

I don't think that's it. I put the code in for loop and threw in a GC.Collect within the loop for good measure and the memory usage just kept going up. I attached a memory profiler and it was saying that most of the used memory was native memory, not managed.

@dlemstra
Copy link
Owner

Can you share your image? It might be related to that image.

@REC-James
Copy link
Author

Sure, I've made a copy of the image with personally identifiable information removed and checked that this image still exhibits the same behaviour. I had to upload it with a .gif extension as GitHub wouldn't allow the WebP extension, but it is a WebP animation. (Rename to .webp if required.)
test
.

@dlemstra
Copy link
Owner

I can reproduce your issue. Thanks for reporting this. Will try to figure out what is causing this tomorrow.

@dlemstra dlemstra added this to the 10.2.0 milestone Mar 17, 2022
@dlemstra
Copy link
Owner

Found and fixed the issue. This will be resolved in the next release of Magick.NET.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants