簡體   English   中英

為什么itext7 for .NET比itextsharp5使用(更多)內存?

[英]Why itext7 for .NET uses (much) more memory than itextsharp5?

我使用itext在.NET環境中生成PDF。 嘗試優化執行時間我正在從itextsharp 5.5.13遷移到.NET的itext 7.1.1。

生成的PDF主要包含圖像。 我使用多線程並行生成文檔。

itext7似乎更快但內存使用率更高。 由於我在同時生成多個文檔,因此內存不足。

我用相同的輸入數據運行了一個簡單的測試,輸出文件是5 MB。 下面是我的兩個版本的庫的代碼。 我的代碼有問題嗎?

itextsharp 5

時間:1:18,內存:峰值173MB,然后穩定在65MB左右

public string GenerateImagesReport(IEnumerable<IChartData> data, string basename)
    {
        var doc = PdfUtility.CreateDoc();

        string path = Shared.BuildPdfPath(basename);
        using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
        {
            PdfWriter writer = PdfWriter.GetInstance(doc, fs);

            float left = 30f;
            float bottom = PdfUtility.GetYPosition(ReportElem.Chart2);
            float width = PdfUtility.CHART_WIDTH;
            float heigth = PdfUtility.CHART_hEIGTH * 2 + PdfUtility.V_SPACE1 + PdfUtility.V_SPACE2 + PdfUtility.GROUP_BY;

            doc.NewPage();
            doc.Open();
            PdfTemplate ImageTemplate;
            PdfContentByte cb = writer.DirectContent;
            Image img;
            foreach (var chart in data)
            {
                // chart image
                ImageTemplate = cb.CreateTemplate(width, heigth);
                img = Image.GetInstance(chart.ImageBytes, true);
                img.ScaleAbsolute(width, heigth);
                img.SetAbsolutePosition(0, 0);
                ImageTemplate.AddImage(img);

                cb.AddTemplate(ImageTemplate, left, bottom);

                chart.DestroyImage();
                doc.NewPage();
            }
            doc.Close();
        }

        return path;
    }

itext 7

時間:1:09,內存:峰值753MB穩定到最后

public string GenerateImagesReport(IEnumerable<IChartData> data, string basename)
    {
        string path = Shared.BuildPdfPath(basename);
        using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
        {
            PdfWriter writer = new PdfWriter(fs);
            var pdf = new PdfDocument(writer);
            var pageSize = PageSize.LETTER;
            var doc = new Document(pdf, pageSize);

            float left = 30f;
            float bottom = PdfUtility.GetYPosition(ReportElem.Chart2);
            float width = PdfUtility.CHART_WIDTH;
            float heigth = PdfUtility.CHART_hEIGTH * 2 + PdfUtility.V_SPACE1 + PdfUtility.V_SPACE2 + PdfUtility.GROUP_BY;

            PdfPage page;
            PdfCanvas canvas;
            ImageData imgd;
            Image img;
            page = pdf.AddNewPage();
            foreach (var chart in data)
            {
                canvas = new PdfCanvas(page, true);

                imgd = ImageDataFactory.Create(chart.ImageBytes);
                img = new Image(imgd, left, bottom);
                img.ScaleAbsolute(width, heigth);

                new Canvas(canvas, pdf, pageSize)
                    .Add(img);

                chart.DestroyImage();
                page = pdf.AddNewPage();
            }

            doc.Close();
        }

        return path;
    }

更新

我正在使用Visual Studio Profiler來監視內存使用情況。 在Yaroslav Veremenko的意見之后,我看到內存使用情況有所改善。 當生成pdf的實際過程開始時,不同的圖表已標記。

與itextsharp 0:43 itextsharp內存使用情況

用itext7 0:26 itext7內存使用情況

with itext7 - page.Flush()0:42 itext7內存使用2

我不熟悉這個庫,但它可能是PdfCanvasCanvas對象在使用后沒有被破壞,並且在文檔被銷毀之前一直存在於內存中。 根據文檔,您必須在繪制圖表后釋放內存。

完成寫入畫布后,請務必調用PdfCanvas.release()。

來源: https://github.com/itext/itext7-dotnet/blob/dd5c209cff35c137ed451fef6e11a96889a52fe9/itext/itext.kernel/itext/kernel/pdf/canvas/PdfCanvas.cs#L69

UPD

我剛剛在本地運行它。 在我的例子中,我有500MB的高峰。 我添加后:

page.Flush(true);

它下降到250MB。

參考: http//itextsupport.com/apidocs/itext7/7.0.2/com/itextpdf/kernel/pdf/PdfPage.html#flush-boolean-

UPD2

有和沒有page.Flush(true)內存使用情況

    foreach (var chart in Enumerable.Range(0, 10))
    {
        canvas = new PdfCanvas(page, true);
        imgd = ImageDataFactory.Create((byte[])converter.ConvertTo(data, typeof(byte[])));
        img = new iText.Layout.Element.Image(imgd, left, bottom);
        img.ScaleAbsolute(width, heigth);
        new Canvas(canvas, pdf, pageSize)
            .Add(img);
        // this line has been added
        page.Flush(true);
        page = pdf.AddNewPage();
    }

圖形

大人們將包裝PdfWriterusing ,因為這實現IDisposable的一個原因和並聯使用時應巨大幫助。 我還刪除了Canvas的實例化,因為當你現有的PdfCanvas對象可以做同樣的事情時,它似乎是不必要的和浪費的。 此外,我已將您的字段移至Foreach范圍,因此GC更有可能收集這些字段。

using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
    using (PdfWriter writer = new PdfWriter(fs)) //**Implements IDisposable - This should help hugely when used in Parallel**
    {
         var pdf = new PdfDocument(writer);
         var pageSize = PageSize.LETTER;
         var document = new Document(pdf);

          foreach (var chart in data)
          {
             var page = pdf.AddNewPage(); //When it get's reassigned on the next iteration, Garbage collection will take over
             PdfCanvas canvas = new PdfCanvas(page, true); //When it get's reassigned on the next iteration, Garbage collection will take over
             canvas.AddImage(ImageDataFactory.Create(chart.ImageBytes), pageSize, false); //1x Less Object in Memory but you will need to play around with params for precision.
             chart.DestroyImage();
          }

          document.Close();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM