在大型PDF上ReadPdf時的高峰記憶體
對於一份整個大型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擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。