DEBUG and RELEASE modeShouldn't there be a ToList on line 177 of CloningImageProcessor{TPixel}.cs?
// We will always be creating the clone even for mutate because we may need to resize the canvas
IEnumerable<ImageFrame<TPixel>> frames = source.Frames.Select<ImageFrame<TPixel>, ImageFrame<TPixel>>(
x => new ImageFrame<TPixel>(
this.Configuration,
targetSize.Width,
targetSize.Height,
x.Metadata.DeepClone()));
The resulting IEnumerable is evaluated 3 times and 3 clones get created, but only 1 is properly disposed (and returned to the ArrayPool).
This results in very weird memory behavior where over time the ArrayPool essentially gets completely bypassed and LOH objects get created on top of the ArrayPool.
When I add ToList, memory behavior is stable and (almost) no Gen 2 collections occur anymore.
Tested on Windows with latest version. And for some reason more problematic in Linux containers (GC behaves differently on that platform?).
Thanks for raising this @silmon27
Can you do two things for me please?
I'm really keen to investigate this issue so that would be really helpful
Sorry, I don't have any graphs or anything of the kind.
I figured the above out by logging all allocations and deallocations (MemoryAllocator) and a found mismatch of 2 after resizing a jpeg image. I think the cause of this should be easy to spot if you take a look at CloningImageProcessor{TPixel}.cs#L177. You pass the IEnumerable to new Image<TPixel> before converting it to a list. Therefore the selector of that Select statement is invoked on every enumeration, thus more than one ImageFrame<TPixel> is instantiated, resulting in a leak.
Hope this helps.
Thanks @silmon27 that's enough to go by. I've just pushed a PR #1074 to fix this.
Even better. Thanks.