-
-
Notifications
You must be signed in to change notification settings - Fork 887
Description
Prerequisites
- I have written a descriptive issue title
- I have verified that I am running the latest version of ImageSharp
- I have verified if the problem exist in both
DEBUGandRELEASEmode - I have searched open and closed issues to ensure it has not already been reported
Description
Usaging ImageSharp beta003, I resize an image with the following code:
using (var image = Image.Load(sourceFileName))
using (var outputFile = File.OpenWrite(target))
{
image.Mutate(ctx => ctx.Resize(newWidth, newHeight));
image.SaveAsJpeg(outputFile);
}I can execute this code a few times but it eventually causes my process to die because of an out-of-memory.
Steps to Reproduce
This code works perfectly fine on my machine (hehe) but when I run in production where memory is more limited, I quickly get out of memory errors. In production, my code runs on linux, on dotnet core 2.0.5 inside of a docker container that is limited to 1 GB of RAM.
The problem occurs with this 6000x6000 jpg.
Here's what I did (each step invokes the code mentionned above, so the image is loaded and resized starting from the file on disk):
- resize to 401x401 => memory increases from 143 MiB to 572 MiB (jump of ~430 MiB)
- resize to 402x402 => memory increases from 572 MiB to 971 MiB which is very close to the memory allocated to my docker container. At this point, I suppose that the garbage collector kicks in because I see my memory dropping back to 369 MB
- resize to 403x403 => memory increases to 548 MiB
- resize to 404x404 => memory increases to 794 MiB
- resize to 405x405 => my process dies with out-of-memory
From step 2 to 3 and 3 to 4, we can see that the minimum memory required to resize an image is a little more than 200 MiB. So when step 5 starts, we can expect a quick demand for more than 200 MiB and the garbage collector does not have the time to free memory before the process dies because it is running out of memory.
So first question: does ImageSharp allocates unmanaged memory that can prevent the garbage collector to properly handle the request for memory involved in step 5? To be more general, do you see something else that could cause this failure?
When we look at these numbers, there is something else interesting: even after the garbage collector run after step 2, the memory did not go all the way down to 143 MiB (the initial level). It only went back to 369 MiB. To investigate that, I tried something on my dev machine: I loaded the same file and checked the memory usage at a few steps:
- Before doing the Image.Load
- After doing the Image.Load
- After disposing the loaded image (thus after saving the resized image as a jpg)
Here's what the process memory usage looked like (as shown by the Visual Studio diagnostic tool... which I don't know if it is totally reliable):
- 68 MB
- 421 MB
- 391 MB
So once again, it looks like there is still something being consumed by ImageSharp after the image is resized.
So second question: Does ImageSharp reserves memory, buffer pools or something else that could cause this high memory consumption even after I am done resizing the image? If yes, is there a way to free this memory? Can I limit this memory?
System Configuration
- ImageSharp version: beta003
- Environment (Operating system, version and so on): docker image based on microsoft/aspnetcore:2.0.5
- .NET Framework version: dotnet core 2.0.5