From 84ca4d23567d5019a3b936d4aedc1cad8e00f4d9 Mon Sep 17 00:00:00 2001 From: "PROGRESS\\ykaraman" Date: Thu, 16 Oct 2025 11:52:09 +0300 Subject: [PATCH 1/2] Document ExpandableMemoryStream. --- _config.yml | 3 ++ .../pdf/expandablememorystream.md | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md diff --git a/_config.yml b/_config.yml index c195db52..a508439b 100644 --- a/_config.yml +++ b/_config.yml @@ -252,6 +252,9 @@ navigation: libraries/radpdfprocessing/formats-and-conversion/pdf/pdfstreamwriter: title: PdfStreamWriter position: 2 + libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream: + title: ExpandableMemoryStream + position: 3 libraries/radpdfprocessing/formats-and-conversion/plain-text: title: Plain Text position: 0 diff --git a/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md b/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md new file mode 100644 index 00000000..5f5b9c90 --- /dev/null +++ b/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md @@ -0,0 +1,45 @@ +--- +title: ExpandableMemoryStream +page_title: ExpandableMemoryStream +description: Learn about the segmented, dynamically growing in-memory stream implementation used for large PDF processing scenarios. +slug: radpdfprocessing-formats-and-conversion-pdf-expandablememorystream +tags: pdf, memory, performance, stream, fixed, document, processing, dpl, format, expandablememorystream, large, file, size +published: True +position: 3 +--- + +# ExpandableMemoryStream + +## Overview + +ExpandableMemoryStream is a segmented in‑memory stream optimized for large or many parallel PDF operations. Instead of resizing one big array, it grows by adding fixed‑size blocks only when needed. This keeps allocations smaller and steadier, helps the GC, and maintains predictable performance as documents scale. Compared to MemoryStream (which resizes one contiguous array and copies data on expansion), this segmented approach adds fixed blocks without copying existing bytes, reducing large reallocations and LOH pressure for very large or unpredictable workloads. The block‑based design grows incrementally without moving existing bytes and supports very large content sizes while keeping allocation behavior stable under parallel load. + +## Why a Segmented Approach + +Large PDF generation often needs a temporary buffer. A normal contiguous array may reallocate and copy data multiple times as it expands, increasing CPU work, peak memory, and pressure on the Large Object Heap (LOH). Avoiding large contiguous allocations lowers fragmentation, reduces garbage collection pauses, and scales better when size is unpredictable or workloads are bursty. + +## How It Works + +Data lives in equal‑sized blocks held in order. When more space is required a single new block is allocated, earlier blocks stay untouched. A position maps to (block index, offset). Growing exposes cleared bytes ready for writing. Shrinking lowers only the visible length and retains the blocks so later growth can reuse already allocated memory without new large allocations. + +## When to Use + +Use it when you need to: + +- Build or merge large PDFs fully in memory before saving. +- Combine many pieces where the final size is unknown. +- Run multiple document builds in parallel and want steady, predictable allocations. +- Seek and rewrite parts of the buffered content without triggering array growth copies. + +## Example + +The following example shows two common ways to load a large PDF document into memory before further processing. The first approach constructs the stream directly from a byte array and passes an explicit segment size (bufferSize). The second approach creates an empty instance and copies a file stream into it. The constructor's second parameter (bufferSize) is optional and defaults to 1,000,000 bytes (1 MB). You can omit it unless you want a different segment size. + + + +In both cases the segmented internal structure avoids reallocating a single large contiguous buffer, helping performance and memory stability for very large PDF files. + +## See Also + +* [PdfFormatProvider]({%slug radpdfprocessing-formats-and-conversion-pdf-pdfformatprovider%}) +* [RadFixedDocument]({%slug radpdfprocessing-model-radfixeddocument%}) From d6229fb2cdfae7b7140d720f6a6b2bf2b1857f38 Mon Sep 17 00:00:00 2001 From: "PROGRESS\\ykaraman" Date: Thu, 16 Oct 2025 12:53:56 +0300 Subject: [PATCH 2/2] polished article. --- .../pdf/expandablememorystream.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md b/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md index 5f5b9c90..649eee08 100644 --- a/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md +++ b/libraries/radpdfprocessing/formats-and-conversion/pdf/expandablememorystream.md @@ -10,17 +10,7 @@ position: 3 # ExpandableMemoryStream -## Overview - -ExpandableMemoryStream is a segmented in‑memory stream optimized for large or many parallel PDF operations. Instead of resizing one big array, it grows by adding fixed‑size blocks only when needed. This keeps allocations smaller and steadier, helps the GC, and maintains predictable performance as documents scale. Compared to MemoryStream (which resizes one contiguous array and copies data on expansion), this segmented approach adds fixed blocks without copying existing bytes, reducing large reallocations and LOH pressure for very large or unpredictable workloads. The block‑based design grows incrementally without moving existing bytes and supports very large content sizes while keeping allocation behavior stable under parallel load. - -## Why a Segmented Approach - -Large PDF generation often needs a temporary buffer. A normal contiguous array may reallocate and copy data multiple times as it expands, increasing CPU work, peak memory, and pressure on the Large Object Heap (LOH). Avoiding large contiguous allocations lowers fragmentation, reduces garbage collection pauses, and scales better when size is unpredictable or workloads are bursty. - -## How It Works - -Data lives in equal‑sized blocks held in order. When more space is required a single new block is allocated, earlier blocks stay untouched. A position maps to (block index, offset). Growing exposes cleared bytes ready for writing. Shrinking lowers only the visible length and retains the blocks so later growth can reuse already allocated memory without new large allocations. +ExpandableMemoryStream is a segmented in-memory stream designed for efficient large or parallel PDF operations. Instead of resizing a single contiguous array like a **MemoryStream**, it grows by adding fixed-size blocks as needed—avoiding costly reallocations and Large Object Heap (LOH) pressure. Each block remains untouched once filled, so data isn’t copied during expansion. This block-based approach keeps allocations small and predictable, reduces GC overhead, and supports very large or bursty workloads. When growing, new cleared blocks are appended. When shrinking, only the visible length changes, allowing future reuse of existing memory without additional allocations. ## When to Use