High Peak Memory During ReadPdf on Large PDFs
Calling BarcodeReader.ReadPdf() once for an entire large PDF renders every requested page for scanning at the configured DPI, so peak memory scales with page count and resolution instead of staying flat. On a 248-page, 80MB file at 300 DPI, memory ran between 3GB and 8GB with spikes to 12GB, enough to fail in memory-limited environments.
BarcodeReader.ReadPdf() processes every page handed to it in a single operation. When the full page range of a large, high-DPI document is read at once, all of those pages are held in memory together, so peak usage grows with the size of the page set. This reflects how the read is batched, not a confirmed defect in IronBarcode.
Solution
1. Read in fixed page chunks
Split the document into fixed page chunks with PdfBarcodeReaderOptions.PageNumbers so only one chunk is in memory at a time. A smaller chunkSize lowers peak memory but adds more passes, so tune it to the environment's memory ceiling.
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}")
Each iteration reads only the pages named in PageNumbers, so memory drops back between chunks rather than accumulating across the whole file.
2. Cache the PDF stream and reset its position
Read the stream into a local once before the loop, then rewind it per chunk. The Stream property may allocate on each access, so store it in var pdfStream = pdf.Stream; and call pdfStream.Seek(0, SeekOrigin.Begin) before each chunk read.
3. Build the reader options once
Construct PdfBarcodeReaderOptions outside the loop and change only PageNumbers per chunk, rather than allocating a fresh options object every iteration.
4. Pre-size the results list
Initialize the results list with an estimated capacity to avoid repeated internal array doubling as results are added. The repro estimates roughly one barcode per ten pages as a starting figure.

