skip to Main Content

Is there any way to diagnose Unmanaged memory leak ?

I am using .NET 5.0 Console App with NETCode (barcode) library. The program it self is simple it calls barcode library & creates a base64string from Image 5000 times, I am using ‘using blocks’ therefore disposing is also being handled.

static void Main(string[] args)
{
    Console.ReadKey();
    for (int i = 0; i < 5000; i++)
    {
        Barcode bar = new Barcode("123456789123456", Type.Code128);
        using (var image = bar.GetImage())
        {
            using (MemoryStream ms = new MemoryStream())
            {
                image.Save(ms,ImageFormat.Png);
                var base64 = Convert.ToBase64String(ms.ToArray());
                Console.WriteLine(i);
            }
        }
    }
    Console.ReadKey();
    Console.ReadKey();
}

On windows this program consumes 15-25 MB (doesn’t go above that) but on Linux Unmanaged memory constantly increases with each iteration but never goes down at all (goes upto 600MB on 5000 iterations).

enter image description here

Linux dotMemory:

enter image description here

enter image description here

Windows dotMemory:

enter image description here

I have tried the same program after fixing the Font, FontFamily disposing issue but the results are same.
I am facing same issue with J4LBarcode, BarcodeLib.

I am using docker with:

FROM mcr.microsoft.com/dotnet/aspnet:5.0.15-focal as base
FROM mcr.microsoft.com/dotnet/sdk:5.0.406-focal AS build

Whole demo with dockerfile & dotmemory snapshots can be found here.

2

Answers


  1. Chosen as BEST ANSWER

    I was able to solve the issue, and the solution applies to anyone using System.Drawing.Bitmap on linux.

    The issue is not related to NetBarcode, System.Drawing.Common (atleast on windows). On linux environment we use libgdiplus. NetBarcode.Barcode.GetImage() creates a bitmap:

    var bitmap = new Bitmap(_width, _height);
    

    This by default creates a bitmap having 32bit depth (RGBA).

    public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb)
    {
    }
    

    I suspect on Linux GDI+ is no properly handling 32bit color images. If you explicitly specify bitmap to use 24Bit:

    var bitmap = new Bitmap(_width, _height, PixelFormat.Format24bppRgb);
    

    The memory leak issue will be fixed.


  2. I will add some discoveries to what Danial Ahmed discovered since we experienced a similar issue, but with .NET 6.

    Adding PixelFormat.Format24bppRgb as a parameter in bitmap creating decreased the memory leak, but didn’t remove it entirely. In our dockerfile, we manually added older version of GDI (4.2), which removed the memory leak.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search