读取大PDF文件时的内存峰值高
对于整个大型PDF,仅调用BarcodeReader.ReadPdf()一次可以按照配置的DPI扫描每个请求的页面,因此峰值内存随页面数量和分辨率缩放,而不是保持不变。 在248页、80MB的文件中,300 DPI下,内存在3GB和8GB之间波动,峰值高达12GB,这足以导致内存有限环境下的失败。
BarcodeReader.ReadPdf()在单个操作中处理交给它的每一页。 当一次性读取大、高DPI文档的整个页面范围时,所有这些页面都会一起保存在内存中,因此峰值使用率随着页面集大小而增长。 这反映了读取是如何分批的,而不是IronBarcode中的一个确凿缺陷。
解决方案
1. 在固定页块中读取
使用chunkSize降低峰值内存但增加更多遍,因此根据环境的内存上限进行调整。
var barcodeMetadata = new List<BarcodeResult>();
var pageChunks = Enumerable.Range(1, pdf.PageCount)
.GroupBy(i => i / 50)
.Select(g => g.ToArray())
.ToList();
foreach (var chunk in pageChunks)
{
var readerOptions = new PdfBarcodeReaderOptions
{
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = IronBarCode.BarcodeEncoding.AllOneDimensional,
Speed = ReadingSpeed.Detailed,
ScanMode = BarcodeScanMode.OnlyDetectionModel,
DPI = 300,
PageNumbers = chunk
};
Console.WriteLine($"Processing pages: Pages {chunk.First()}-{chunk.Last()}");
var chunkResult = BarcodeReader.ReadPdf(pdf.Stream, readerOptions);
if (chunkResult != null && chunkResult.Count > 0)
{
barcodeMetadata.AddRange(chunkResult);
}
// Optional memory pressure relief
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"Total barcodes found: {barcodeMetadata.Count}");
var barcodeMetadata = new List<BarcodeResult>();
var pageChunks = Enumerable.Range(1, pdf.PageCount)
.GroupBy(i => i / 50)
.Select(g => g.ToArray())
.ToList();
foreach (var chunk in pageChunks)
{
var readerOptions = new PdfBarcodeReaderOptions
{
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = IronBarCode.BarcodeEncoding.AllOneDimensional,
Speed = ReadingSpeed.Detailed,
ScanMode = BarcodeScanMode.OnlyDetectionModel,
DPI = 300,
PageNumbers = chunk
};
Console.WriteLine($"Processing pages: Pages {chunk.First()}-{chunk.Last()}");
var chunkResult = BarcodeReader.ReadPdf(pdf.Stream, readerOptions);
if (chunkResult != null && chunkResult.Count > 0)
{
barcodeMetadata.AddRange(chunkResult);
}
// Optional memory pressure relief
GC.Collect();
GC.WaitForPendingFinalizers();
}
Console.WriteLine($"Total barcodes found: {barcodeMetadata.Count}");
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports IronBarCode
Dim barcodeMetadata As New List(Of BarcodeResult)()
Dim pageChunks = Enumerable.Range(1, pdf.PageCount) _
.GroupBy(Function(i) i \ 50) _
.Select(Function(g) g.ToArray()) _
.ToList()
For Each chunk In pageChunks
Dim readerOptions As New PdfBarcodeReaderOptions With {
.ExpectMultipleBarcodes = True,
.ExpectBarcodeTypes = BarcodeEncoding.AllOneDimensional,
.Speed = ReadingSpeed.Detailed,
.ScanMode = BarcodeScanMode.OnlyDetectionModel,
.DPI = 300,
.PageNumbers = chunk
}
Console.WriteLine($"Processing pages: Pages {chunk.First()}-{chunk.Last()}")
Dim chunkResult = BarcodeReader.ReadPdf(pdf.Stream, readerOptions)
If chunkResult IsNot Nothing AndAlso chunkResult.Count > 0 Then
barcodeMetadata.AddRange(chunkResult)
End If
' Optional memory pressure relief
GC.Collect()
GC.WaitForPendingFinalizers()
Next
Console.WriteLine($"Total barcodes found: {barcodeMetadata.Count}")
每次迭代仅读取PageNumbers中命名的页面,因此内存在块之间会下降,而不是在整个文件中累积。
2. 缓存PDF流并重置其位置
在循环之前将流读取到本地一次,然后在每个块时倒回。pdfStream.Seek(0, SeekOrigin.Begin)。
3. 构建一次读取器选项
在循环外构造PageNumbers,而不是每次迭代都分配一个新的选项对象。
4. 预先设定结果列表大小
通过预估容量初始化结果列表,以避免在添加结果时反复的内部分组倍增。 该复现初步估计每十页大约一个条码作为起点。

