Release/Reduce ImageSharp Memory Usage After Use

1.1k views Asked by At

I have created a test WPF application for the testing of SixLabors.ImageSharp to see how it performed and if it met some requirements etc before any integration into a production application.

My test app consists of an Image control to display the image that will be maniplulated and a few buttons to load an image, rotate, apply rotation.

When the app launches, it consumes roughly ~30-40MB of system memory.

However, as soon as I apply a rotation to the image using the below code and save back to disk the memory usage goes from it's ~25-40MB to ~300-500MB.

If I apply a second rotation to the image, the memory usage goes up again to somewhere around ~600-800MB.

If I apply a third rotation to the image, the memory usage goes up again to somewhere around ~850-1,000MB.

If I apply a fourth rotation to the image, the memory usage drops to around where the first rotation was performed, somewhere ~300-500MB.

I am specifying that the application uses MinimalPooling to attempt to keep the memory usage down.

Configuration.Default.MemoryAllocator = ArrayPoolMemoryAllocator.CreateWithMinimalPooling();

Rotation code

private void ApplyRotation()
{
    string output;

    using (SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(imageToProcess))
    {
        // Decide based on the angle which rotation to use/
        // Rotate the image in place.
        // 'x' signifies the current image processing context.

        switch (angle)
        {
            case 0:
            case 360:

                break;

            case 90:
                image.Mutate(x => x.Rotate(RotateMode.Rotate90));

                break;

            case 180:
                image.Mutate(x => x.Rotate(RotateMode.Rotate180));

                break;
            case 270:
                image.Mutate(x => x.Rotate(RotateMode.Rotate270));

                break;

        }

        // The library automatically picks an encoder based on the file extension then
        // encodes and write the data to disk.
        // You can optionally set the encoder to choose.
        output = imageToProcess;

        image.Save(output);
    }
}

Looking at the ImageSharp Documentation it states that ImageSharp retains roughly 300-400MB of memory due to their use of ArrayPools. This explains the first memory jump when the library is first used, however the subsequent jumps in memory usage I don't understand or know how to release.

I have used

Configuration.Default.MemoryAllocator.ReleaseRetainedResources();

as found in their documentation which I believe should release the resources that are being held onto. This does not seem to be the case. If I apply 3 rotations to my image and the memory usage is sat around 1GB, at no point in the application running will this reduce back to less than 300MB, even if the controls are being used on another window and then closed afterwards.

Does anyone know how to reduce this memory usage or dispose of eveyrthing so the memory usage returns to normal.

Thanks

1

There are 1 answers

0
James South On

I am specifying that the application uses MinimalPooling to attempt to keep the memory usage down.

This doesn't do what you think it does. By minimizing pooling you are telling ImageSharp to use standard managed allocations which, in turn, will only get cleaned up when the GC gets around to it.

Configuration.Default.MemoryAllocator.ReleaseRetainedResources();

Releases memory from pooled resources so will have no effect on that non-pooled allocated memory.

I would generally stick with the defaults as messing around with them requires a deep understanding of how memory is allocated and managed.

ImageSharp v2 and later use pool chunks of unmanaged memory by default and provides lifetime management of those chunks. This memory management is designed to be as efficient as possible.