Optimising Image Processing


Investigating old code

In my previous article, we covered how we found and solved a fixed cost of using PutObject on the AWS S3 .NET client; it was also mentioned that we transform the image before it is uploaded to AWS S3 - this is a process that is executed at least 500,000 times a day. With that in mind I decided it was worth exploring the entire code path. As always you can find all the code talked about here, and we will be using this image in our testing. Let us take a look at the existing implementation. Before we can transform an image we need to get a hold of it:-

Total Images: 14,630
Images Above LOH Threshold: 14,276
Average Image Size: 253,818 bytes
Largest Image Size: 693,842 bytes
Smallest Image Size: 10,370 bytes
Standard Deviation of Sizes: 101,184

Streaming is winning

If we inline the GetImageFromUrl and remove the CanCreateImageFrom - which is not needed because we check the Content-Type earlier in the code path (not shown), we can directly operate on the incoming stream.

Pool your streams

Using dotTrace again, we can see the next biggest cost:-

Goodbye System.Drawing, you will not be missed

My knowledge on System.Drawing is pretty sketchy but an afternoon reading about it leads me to the conclusion that if you can avoid using System.Drawing then you are better off. Whilst searching for an alternative to System.Drawing, I came across this article written by Omar Shahine. Huh, I never considered the overloads. Takes two seconds to try this so we might as well; v3 with useEmbeddedColorManagement disabled and validateImageData turned off these are the stats:-

In the interest of transparency

Pun not intended — just before this article was about to be published I saw this interesting tweet:-

  1. Still working on improving their JPEG decoder — this is relevant because we process other image formats too despite only focusing on a JPEG image this article
  2. Aware that their resizing algorithm is not as optimal as it could be — this is relevant because the main part of the transformation we do is resizing

TLDR — tell me what to do

If your image transformation process is mostly resizing and you are hosted on Windows then look into using PhotoSauce.MagicScaler with Microsoft.IO.RecyclableMemoryStream you will see a significant reduction in various performance related metrics. In our case sixty to ninety percentage reductions.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store