-
-
Notifications
You must be signed in to change notification settings - Fork 855
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
OutOfMemoryException when loading png image #248
Comments
Very odd, it's only a small png which I can decode/encode no problem. Could you share some code samples? Are you running in 32bit or 64bit mode? Are there any other contributory factors that could be eating up memory? |
I made a very basic console project with minimal code and the exact same exception is thrown : ISFailure.zip. I run it from Visual Studio for Mac :
Maybe it could be linked to the Preview version of VS ? |
Looks like this might be a mono related issue, I've not managed to reproduce the exact error but I've definitely managed to reproduce related issues running the exe with the latest preview release of mono on windows (just failing to figure out how to debug it.) 😞 On windows i'm seeing: Unhandled Exception:
ImageSharp.ImageFormatException: Unknown filter type.
at ImageSharp.Formats.PngDecoderCore.DecodePixelData[TPixel] (System.IO.Stream compressedStream, ImageSharp.Image`1[TPixel] image) [0x000fd] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Formats.PngDecoderCore.ReadScanlines[TPixel] (System.IO.Stream dataStream, ImageSharp.Image`1[TPixel] image) [0x00017] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Formats.PngDecoderCore.Decode[TPixel] (System.IO.Stream stream) [0x00186] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Formats.PngDecoder.Decode[TPixel] (ImageSharp.Configuration configuration, System.IO.Stream stream, ImageSharp.Formats.IPngDecoderOptions options) [0x00007] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Formats.PngDecoder.Decode[TPixel] (ImageSharp.Configuration configuration, System.IO.Stream stream, ImageSharp.IDecoderOptions options) [0x00007] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.Decode[TPixel] (System.IO.Stream stream, ImageSharp.IDecoderOptions options, ImageSharp.Configuration config) [0x00013] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image+<>c__DisplayClass36_0`1[TPixel].<Load>b__0 (System.IO.Stream s) [0x00000] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.WithSeekableStream[T] (System.IO.Stream stream, System.Func`2[T,TResult] action) [0x0001b] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.Load[TPixel] (ImageSharp.Configuration config, System.IO.Stream stream, ImageSharp.IDecoderOptions options) [0x00029] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.Load[TPixel] (ImageSharp.Configuration config, System.String path, ImageSharp.IDecoderOptions options) [0x00019] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.Load[TPixel] (System.String path) [0x00000] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ImageSharp.Image.Load (System.String path) [0x00000] in <ba1825465e5b4bb4bfdd088e15832d97>:0
at ISFailure.MainClass.Main (System.String[] args) [0x00001] in <6b69b8d368354f40acb76e45b659b70a>:0 My theory is something in Mono is corrupting the stream and causing the image load to fail. |
@tocsoft That would suggest an issue with @aloisdeniel Really not sure what to do about this. It seems to be a tooling issue. 😞 |
might be worth us investigating to see if we can port over our usage of DeflateStream over to https://github.com/icsharpcode/SharpZipLib and switch over to using that if
basically not include it in our outputted nuget dependencies just document the workaround for people using mono. |
Nah, I'd rather raise a bug in the Mono repo. SharpZibLib is way slower. |
We have ran into this issue on Windows. We had previously ran into this issue: #290, so we upgraded from 1.0.0-alpha9-00175 to 1.0.0-alpha9-00194. We also tried the OPs image, and that worked ok. Stacktrace
System Configuration ImageSharp version: 1.0.0-alpha9-00194 |
@carcer What about the latest build? Drop me an email and I'll see if I can replicate it. |
We didn't notice there was a beta on nuget.org, apologies. Testing this now. |
@JimBobSquarePants Issue persists with beta0001
I have a note of your email and will send the image over now, if you want to edit it out of your reply |
Great. It's very late here now so I'll have a look tomorrow. |
@carcer I've tested against the image you sent (thanks for that) using the latest code and everything is decoding correctly for me. Silly question but.... You're disposing of your images yeah? |
@JimBobSquarePants Fair question, I double checked and every thing looks. We've been using the alpha for a while now and haven't had an issues, saving the image as a JPG and processing it works fine. Still, it does point to something we might be doing. I will look into it some more over the weekend. 👍 |
Good man, let me know how you get on. 😄 |
I am getting this issue as well We are calling the image operations concurrently. Does this affect the memory allocation? Is there some work around we can use?
|
Looking at the stacktrace that error is throwing in the jpeg decoder, it hasn't hit png yet. What's your |
Thanks @JimBobSquarePants here is the method you asked about.
I have not configured anything regarding arrays so I assume it is doing the default. Not sure what that would be? I would think that we are creating new arrays every time because each image task is being created from the MVC controller |
@houseme-brandon looks like your doing a chain of unnecessary transformations on very large data buffers. Can you try CryptoStream to decode your base64 input, and feed the result stream to |
@houseme-brandon I can immediately see two non-pooled arrays both in That will be where you are using up all your memory. Look up |
[ The example I found is not the best one, because it's writing the stream, you need to read it :) ] |
I have implemented the CyrptoStream which removes the non-pooled arrays as far as I can see. I am handling the disposing of objects as far as I can see.
Still getting the out of memory exception. The only option I can see is to use an ArrayPool directly as I retrieve the image. Am I still missing something? |
@houseme-brandon have you any information about the typical sizes of the images you test your application with? Can you share some of them? Also: can you try to attach a memory profiler to your application following these instructions, and share your results with us? (Make sure you choose "Memory usage" instead of CPU). It would be very helpful both for you and us! :) |
@antonfirsov typical sizes is difficult to say. But I have an example of a batch of images that I got permission to share. This is a link to the pictures I was talking about with an image of azure's memory profile. The memory profile does seem to peak at about 40% and that is when I am loading images. It is strange to me that it never gets higher than that but complains about out of memory but I assume that this is something to do with the garbage collector. I have not seen this issue when running the program locally. It only occurs on azure. I will try run the azure in debug mode with a remote debugger to see if I can get more information about the memory profile. I really appreciate all the help because our users are getting an unpleasant experience at the moment! |
@houseme-brandon those are pretty large images! After a quick calculation, it seems that each What is the memory limit of your VM/app service? Also: Make sure you are running it in a 64 bit process. My current assumption is that, our internal array pool is growing beyond your memory limit before getting into a balanced state when it stops growing. As a first step, it would be nice to prove this. Unfortunately, the memory profile you posted doesn't help. We need something much more detailed, with information about the object graphs. VS memory profiler, or ReSharper memory profiler could do the job. |
The server has 7GB ram. I did set it to run as a 64 bit process but the fact that it is running out of memory at 40% makes me think it is actually running as a 32 bit process. I just checked and it is starting the as x86 even though I specified x64 in azure and built it as AnyCpu. Makes sense that these issues are happening in azure and not on my local PC. I am struggling to get it to start it as 64 bit on azure but will get back to you when I get it right. Going to try and get some more detailed memory profile as well. |
@houseme-brandon If you're running in 32bit mode it will be a lack of contiguous memory that's your issue. Shift to 64bit and you should be fine. I'm actually impressed that we were able to run images of those dimensions. I've seen System.Drawing balk at less in 32bit mode. |
Thanks! So the issue started by changing to dotnet core. We were System.Drawing successfully on dotnet framework because it was running as a 64 bit process. It lost the runtime environment when we changed to dotnet core. Now that it is finally able to start as a 64 bit process again it seems to run flawlessly! Sorry for hikackjing this issue since it turned out to not be related . . . or even an issue |
Discussions like this are great for other readers who run into the same problem. I'm just glad you got it sorted. 😄 |
Wondering if anyone solved that for Azure AppService running .NET Core 2 (not 2.1). Looks like having 64bit Core runtime requires some effort and not just a toggle in AppService properties |
We've got #431 in the works just now which should dramatically reduce the amount of memory we consume when pooling plus give some options to configure your own memory providers. That said, I'd always recommend 64bit for anything that requires working with images in the megapixels. |
I see. Thing is it's crashing now :) so I can't wait for 431 though I would appreciate it by updating NuGet next release 👏 My image is small in size (2.8M) but large in pixels - 7500x5000. Also looking at the code and comparing how people do resize images using this library, I want to try another trick - if that helps, I'll be good. Since we're here, the issue itself was annoying not because of the crash but because of the fact no developer could reproduce the problem - Visual Studio trained everyone to have lots of RAM. Would be nice to have some kind of diagnostics that would pop the issue in development and not in production when it's a bit late : |
Are you using the beta2 release? @antonfirsov did some interim work in a recent nightly to reduce pooling consumption that might help you. I would grab that from MyGet and see if it helps. Also, if you can get away without transparency try loading the image in That's a big image though which will always cause problems on 32bit systems due to the limits on available contiguous memory. |
Beta 2. Is there anything fresher/better? I don't need transparency probably, though I would love to have it there just cause it could be... Part of the problem is that I can limit binary file size for upload but then image could be small as a file but could have large size in pixels and it will lead to OOM anyway. |
@alexsorokoletov are you using our nightlies? If not, can you try them? There was some improvement with #436. If yous still have the crashes with the nightlies, can you help us by describing your use case? How many requests do you have before the crash? Are those large images outliers or typical? |
Meanwhile, I've refactored code and instead of using Clone + Resize to generate multiple sizes of the image I start with the largest needed size and use Mutate + Resize going down to smaller. Deployed and so far runs good in Azure 32bit on this image (for now). I can try nightly builds, yes. On your questions, Anton:
Users upload pictures for avatars to the website, we keep large and small thumbnail of these pictures.
Before changing Clone + Resize -> Mutate - just one :)
Typical, testing on images from https://unsplash.com/ |
I did some really simple tests on nightly 1.0.0-dev000706 and beta 1.0.0-beta0002 with Rgba32 and Rgb24: Nightly: Job=Nightly1.0.0-dev000706 LaunchCount=1 RunStrategy=ColdStart
Job=Beta1.0.0-beta0002 LaunchCount=1 RunStrategy=ColdStart
I wanted to compare memory savings from beta/nightly and also Rgba32 vs Rgb24 but for some reason allocation is wrong for beta build (maybe it was built way too long ago). For some reason beta works faster ~14%, and Rgba32 doesn't give huge memory savings so I will stay with beta0002 and Rgba32. Thank you :) |
You can't stay on beta forever... 😄 If you read #431 You'll understand why there is more memory allocated for your benchmark. We were creating too large an object pool in the beta so while you are seeing only low allocations in your benchmark, you're not seeing the pre-allocated memory that was set aside for the array pool. Memory that is locked away for nothing else but ImageSharp to use for the entire run-time of the application. The nightly reduces this pooling and allows the garbage collector to much more effectively free up contiguous memory and avoid Out of Memory Exceptions. Smaller images that lie within the pool bounds still use pooled memory. The beta is also faster than the nightly because we were incorrectly missing alpha pre-multiplication as part of the resampling process which let to errors when resizing images with semi transparent pixels. Adding the overhead of premultiplication slows performance down but also fixes what would have been quite a major bug.
|
Can someone test this issue please against the latest nightlies. We've squashed several png bugs and completely rewritten memory management to half the memory used by default. |
@JimBobSquarePants once we plan to update the website where we use the package, I'll be glad to test the new version. Maybe we can setup a dotnet benchmark-based test that tracks allocations and tries to get like 10 images from unsplash and convert them? |
Thanks @alexsorokoletov I'm fairly certain we've squashed the issues around this now but yeah, it could be an idea to do something like that. 👍 |
Description
I get a
OutOfMemoryException
when I load a png image exported from the mac previewer.StackTrace:
Steps to Reproduce
System Configuration
The text was updated successfully, but these errors were encountered: