c# - 为什么 .NET 的 itext 7 使用比 itextsharp 5(多)多的内存?

标签 c# .net itext pdf-generation

我正在使用 itext 在 .NET 环境中生成 PDF。为了优化执行时间,我正在从 itextsharp 5.5.13 迁移到 itext 7.1.1 for .NET。

生成的 PDF 主要由图像组成。我使用多线程并行生成文档。

itext7 似乎更快,但内存使用率更高。由于我同时生成了多个文档,因此内存不足。

我用相同的输入数据运行了一个简单的测试,输出文件是 5 MB。下面是我为两个版本的库编写的代码。我的代码有问题吗?

itextsharp 5

时间:1:18,RAM:峰值 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,RAM:峰值 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 memory usage

使用 itext7 0:26 itext7 memory usage

使用 itext7 - page.Flush() 0:42 itext7 memory usage 2

最佳答案

我不熟悉这个库,但可能是 PdfCanvasCanvas 对象在使用后没有被销毁,一直坐在内存中直到文档被销毁. 根据文档,您必须在绘制图表后释放内存。

Make sure to call PdfCanvas.release() after you finished writing to the canvas.

来源: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();
    }

graph

关于c# - 为什么 .NET 的 itext 7 使用比 itextsharp 5(多)多的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49907865/

相关文章:

java - 如何修复线程 "main"java.lang.NoClassDefFoundError : com/itextpdf/text/DocumentException中的异常

c# - itextsharp 如何添加一个完整的换行符

c# - 打印 RDLC 报告而不显示 ReportViewer 控件

c# - 列出 KeyVault 中的 secret 而无需登录每个 secret ?

c# - 创建日期和 File.Copy 问题

c# - 如何在 Winforms 中将枚举转换为 bool 值以进行数据绑定(bind)?

java - Visual Basic,预期语句结束 - 数组?

c# - 当 selectedItem 为 null 时,在 Combobox 中显示 "Select an item"

mysql - 访问 mysql 数据库并将其显示在 gridview 或表中

css - OnEndPage 事件和带有 RowSpan 的表