读取大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}");
每次迭代仅读取PageNumbers中命名的页面,因此内存在块之间会下降,而不是在整个文件中累积。
2. 缓存PDF流并重置其位置
在循环之前将流读取到本地一次,然后在每个块时倒回。pdfStream.Seek(0, SeekOrigin.Begin)。
3. 构建一次读取器选项
在循环外构造PageNumbers,而不是每次迭代都分配一个新的选项对象。
4. 预先设定结果列表大小
通过预估容量初始化结果列表,以避免在添加结果时反复的内部分组倍增。 该复现初步估计每十页大约一个条码作为起点。

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。