Как обнаружить утечку памяти - PullRequest
0 голосов
/ 14 февраля 2012

У меня есть сомнения, что эта часть кода вызывает утечку памяти:

    public FileResult ShowCroppedImage(int id, int size)
    {
        string path = "~/Uploads/Photos/";
        string sourceFile = Server.MapPath(path) + id + ".jpg";

        MemoryStream stream = new MemoryStream();
        var bitmap = imageManipulation.CropImage(sourceFile, size, size);
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        Byte[] bytes = stream.ToArray();
        return File(bytes, "image/png");
    }

Как я могу сделать тест, чтобы увидеть, является ли этот кусок кода причиной?

РЕДАКТИРОВАТЬ:

public Image CropImage(string sourceFile, int newWidth, int newHeight)
        {
            Image img = Image.FromFile(sourceFile); 
            Image outimage;

            int sizeX = newWidth;
            int sizeY = newHeight;

            MemoryStream mm = null;

            double ratio = 0;
            int fromX = 0;
            int fromY = 0;

            if (img.Width < img.Height)
            {
                ratio = img.Width / (double)img.Height;
                newHeight = (int)(newHeight / ratio);
                fromY = (img.Height - img.Width) / 2;
            }
            else
            {
                ratio = img.Height / (double)img.Width;
                newWidth = (int)(newWidth / ratio);
                fromX = (img.Width - img.Height) / 2;
            }
            if (img.Width == img.Height)
                fromX = 0;

            Bitmap result = new Bitmap(sizeX, sizeY);

            //use a graphics object to draw the resized image into the bitmap 
            Graphics grPhoto = Graphics.FromImage(result);

            //set the resize quality modes to high quality 
            grPhoto.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            grPhoto.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //draw the image into the target bitmap 
            //now do the crop            
            grPhoto.DrawImage(
                img,
                new System.Drawing.Rectangle(0, 0, newWidth, newHeight),
                new System.Drawing.Rectangle(fromX, fromY, img.Width, img.Height),
                System.Drawing.GraphicsUnit.Pixel);


            // Save out to memory and get an image from it to send back out the method.
            mm = new MemoryStream();
            result.Save(mm, System.Drawing.Imaging.ImageFormat.Jpeg);
            img.Dispose();
            result.Dispose();
            grPhoto.Dispose();
            outimage = Image.FromStream(mm);

            return outimage;
        }

Ответы [ 3 ]

3 голосов
/ 14 февраля 2012

Я бы написал это как

public FileResult ShowCroppedImage(int id, int size)
{
    string path = "~/Uploads/Photos/";
    string sourceFile = Server.MapPath(path) + id + ".jpg";

    using (MemoryStream stream = new MemoryStream())
    {
        using (Bitmap bitmap = imageManipulation.CropImage(sourceFile, size, size))
        {
            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            Byte[] bytes = stream.ToArray();
            return File(bytes, "image/png");
        }
    }
}

, чтобы гарантировать, что stream.Dispose и bitmap.Dispose вызываются.

0 голосов
/ 14 февраля 2012

Поскольку вопрос заключался в том, как обнаружить утечки / использование памяти, я бы рекомендовал написать метод, который вызывает вашу функцию, записывающую использование памяти до и после:

public void SomeTestMethod()
{
    var before = System.GC.GetTotalMemory(false);
    // call your method
    var used = before - System.GC.GetTotalMemory(false);
    var unreclaimed = before - System.GC.GetTotalMemory(true);
}

Before будет измерять использование памяти перед выполнением вашей функции. Используемая переменная будет содержать объем памяти, использованный вашей функцией до того, как сборщик мусора был запущен, а необработанный сообщит вам, сколько байт использовалась вашей функцией даже после попытки очистить ваши объекты.

Я подозреваю, что используемое будет высоким, а невостребованное - нет. Использование этого потока памяти, как предлагают другие авторы, должно сблизить их, хотя имейте в виду, что у вас все еще есть байтовый массив, удерживающий память.

0 голосов
/ 14 февраля 2012

Может хотеть позвонить stream.dispose(); после Byte[] bytes = stream.ToArray();.

...