Büyük PDF'lerde ReadPdf Sırasında Yüksek Zirve Belleği
Büyük bir PDF için yalnızca bir kez BarcodeReader.ReadPdf() çağrıldığında, talep edilen her sayfa ayarlanan DPI'de tarama için işlenir, böylece tepe bellek sayfa sayısı ve çözünürlük ile birlikte ölçeklenir, düz bir seviyede kalmaz. 248 sayfalık, 80MB dosyada 300 DPI'da bellek 3GB ile 8GB arasında çalıştı, 12GB'a kadar sıçradı, hafıza sınırlı ortamlarda başarısız olmaya yetecek kadar.
BarcodeReader.ReadPdf() kendisine verilen her sayfayı tek bir işlemde işler. Tam sayfa aralığı büyük, yüksek-DPI belgede bir defada okunduğunda, tüm bu sayfalar bellekle birlikte tutulur, bu nedenle zirve kullanımı sayfa setinin boyutuyla büyür. Bu, okuma toplu işlenmesinin nasıl yapıldığını yansıtır, IronBarcode'un teyit edilmiş bir hatası değildir.
Çözüm
1. Sabit sayfa parçaları halinde okuyun
Belgeleri sabit sayfa parçalarına bölmek için PdfBarcodeReaderOptions.PageNumbers kullanın, böylece her seferinde yalnızca bir parça bellekte kalır. Daha küçük bir chunkSize tepe belleği düşürür ancak daha fazla geçiş ekler, bu yüzden bunu ortamın bellek sınırına göre ayarlayın.
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}")
Her yineleme, sadece PageNumbers içinde adlandırılan sayfaları okur, bu nedenle bellek tüm dosya boyunca birikmek yerine parçalar arasında düşer.
2. PDF akışını önbelleğe alın ve konumunu sıfırlayın
Akışı döngüden önce bir kez yerel bir değişkene okuyun ve sonra her parça için geri sarın. Stream özelliği her erişimde tahsis edebilir, bu yüzden bunu var pdfStream = pdf.Stream; içinde depolayın ve her parça okumadan önce pdfStream.Seek(0, SeekOrigin.Begin) çağırın.
3. Okuyucu seçeneklerini bir kez oluşturun
PdfBarcodeReaderOptions döngü dışında kurun ve her döngüde taze bir seçenekler nesnesi tahsis etmek yerine yalnızca PageNumbers parça başına değiştirin.
4. Sonuçlar listesini önceden boyutlandırın
Sonuçlar eklenirken iç dizi boyutlandırmasının tekrarını önlemek için tahmin edilen kapasitede sonuçlar listesini başlatın. Yineleme yaklaşık her on sayfa başına bir barkod başlangıç sayısı tahmin eder.

