Wysokie zuzycie pamieci szczytowej podczas ReadPdf na duzych plikach PDF

This article was translated from English: Does it need improvement?
Translated
View the article in English

Wywolanie BarcodeReader.ReadPdf() raz dla calego duzego PDF renderuje kazda zadana strone do skanowania w skonfigurowanej rozdzielczosci DPI, zatem szczytowa pamiec skalowana jest z liczba stron i rozdzielczoscia zamiast pozostawac stala. W pliku o rozmiarze 248 stron, 80 MB przy 300 DPI, pamiec miescila sie miedzy 3 GB a 8 GB, z naglymi wzrostami do 12 GB, co wystarczalo na blad w srodowiskach z ograniczona pamiecia.

BarcodeReader.ReadPdf() przetwarza kazda strone przekazana mu w jednej operacji. Gdy cala gama stron duzego dokumentu o wysokim DPI zostaje odczytana naraz, wszystkie te strony sa przetrzymywane w pamieci razem, co sprawia, ze szczytowe zuzycie rosnie w zaleznosci od wielkosci zestawu stron. Odzwierciedla to sposob przetwarzania paczek odczytu, a nie potwierdzony defekt w IronBarcode.

Rozwiązanie

1. Odczytywanie w stalych segmentach stron

Podziel dokument na stale fragmenty stron za pomoca PdfBarcodeReaderOptions.PageNumbers, aby tylko jeden fragment byl w pamieci naraz. Mniejszy chunkSize zmniejsza szczytowa pamiec, ale dodaje wiecej przejsc, wiec dostosuj go do limitu pamieci srodowiska.

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}")
$vbLabelText   $csharpLabel

Kazda iteracja odczytuje tylko strony wymienione w PageNumbers, wiec pamiec spada pomiedzy fragmentami zamiast kumulowac sie przez caly plik.

2. Buforuj strumien PDF i zresetuj jego pozycje

Odczytaj strumien do lokalnego przed petla, a nastepnie przewijaj go po kazdym fragmencie. Wlasciwosc Stream moze przydzielac na kazdym dostepie, wiec przechowuj ja w var pdfStream = pdf.Stream; i wywoluj pdfStream.Seek(0, SeekOrigin.Begin) przed kazdym odczytem fragmentu.

3. Zbuduj opcje czytnika raz

Skonstruuj PdfBarcodeReaderOptions poza petla i zmien tylko PageNumbers dla kazdego fragmentu, zamiast przydzielac nowy obiekt opcji za kazda iteracja.

4. Wstepnie odstaw liste wynikow

Zainicjuj liste wynikow z szacowana pojemnoscia, aby uniknac powtarzajacego sie podwajania wewnetrznej tablicy podczas dodawania wynikow. Rekord szacuje na poczatek, ze na dziesiec stron przypada jeden kod kreskowy.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 2,317,217 | Wersja: 2026.7 właśnie wydany
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package BarCode
uruchom przykład zobacz, jak twoje ciągi zamieniają się w kody kreskowe.