[Question] Native Memory Accumulation & File Mapping Behavior during High-Volume Printing (Interpretation Mode)

Stimulsoft Reports.NET discussion
Post Reply
Liam
Posts: 4
Joined: Mon Sep 29, 2025 8:03 am

[Question] Native Memory Accumulation & File Mapping Behavior during High-Volume Printing (Interpretation Mode)

Post by Liam »

Hi everyone,

I am currently working on a background printing service using Stimulsoft Reports [2023.1.2.0/2020.2.1.0] in a .NET 4.5.2 environment. The task involves loading and printing reports in a loop (approx. 10,000 iterations per batch).

I’ve been troubleshooting some memory usage behaviors and would like to share my findings to see if anyone has encountered similar issues or can suggest a "Best Practice" for cleanup.

Here is the timeline of my investigation:

1. Initial Setup (Standard Mode)

Initially, running the loop with default settings caused a rapid memory increase. This appeared to be related to dynamic assembly generation/loading.

I resolved this by switching to Interpretation Mode, which successfully stabilized the managed memory:|

Code: Select all

report.CalculationMode = StiCalculationMode.Interpretation;
StiOptions.Engine.ReportCache.AllowGCCollect = true;
2. The Current Challenge: Native Memory Creep

After switching to Interpretation Mode, the application became much more stable. However, I noticed a slow but continuous growth in Native Memory (Private Bytes), increasing from ~20MB to ~100MB over 10,000 iterations.

I analyzed a dump using Windbg. The Managed Heap looks healthy, but the Native Heap shows an accumulation of small blocks (Size: 0x851 / 2129 bytes).

Windbg Output (Native Heap Analysis):
It looks like thousands of small GDI+ related objects (possibly cached icons or image data?) are persisting.

Code: Select all

0:000> !heap -stat -h 0000026fa3d40000
    size     #blocks     total     ( %)
    851      729c        3b9235c   (93.58)  <-- Approx 30,000 blocks accumulated
    ...
3. Attempting to Fix via Cache Clearing (Unexpected Behavior)
Thinking these native blocks were cached resources, I tried to manually clear the engine cache inside the loop:

Code: Select all

// My attempt to release the native blocks
StiReport.ClearImageCache();
StiReport.ClearReportCache();
The Result: unexpectedly, this caused memory usage to increase much faster, eventually leading to an OOM condition.
Upon checking the dump again, I found a massive explosion in MEM_MAPPED regions, while the actual File Handle count remained low (~80).

Windbg Output (Address Summary):

Code: Select all

0:000> !address -summary
--- Type Summary (for busy) ------ RgnCount
MEM_PRIVATE                            3370
MEM_IMAGE                              1368
MEM_MAPPED                             5725  <-- Significant increase in Mapped regions
It seems that repeatedly clearing the cache forces the engine to reload resources, but the old file mappings (Views) might not be getting unmapped correctly.

Code Reproduction
Here is the simplified logic I am using:

Code: Select all

for (int i = 0; i < 10000; i++)
{
    using (StiReport report = new StiReport())
    {
        report.Load(filePath);
        // Optimization from Step 1
        report.CalculationMode = StiCalculationMode.Interpretation; 
        
        report.Render(false);
        
        // ... Printing logic ...
        
        report.RenderedPages.Clear();
    } // Report is Disposed here

    // Step 3: Adding 'StiReport.ClearImageCache()' here caused the MEM_MAPPED explosion.
}
My Questions
1.Is the slow accumulation of Native GDI objects (Step 2) expected in Interpretation Mode? Is there a specific way to flush them?

2.Regarding the file mapping issue in Step 3: Is it unsafe to call ClearImageCache() repeatedly in a loop?

3.Are there any recommended patterns for completely releasing all resources (Native GDI & Mappings) to run a 24/7 printing service without memory drift?
Any insights or suggestions would be greatly appreciated. Thanks!
Liam
Posts: 4
Joined: Mon Sep 29, 2025 8:03 am

Re: [Question] Native Memory Accumulation & File Mapping Behavior during High-Volume Printing (Interpretation Mode)

Post by Liam »

Originally, after switching to report.CalculationMode = StiCalculationMode.Interpretation;, I thought I had resolved the issue of dynamic assembly generation/loading (and it did stabilize managed memory). However, analysis via the !dumpdomain command in WinDbg revealed that a large number of suspected anonymous dynamically compiled assemblies are still being generated. The specific output is as follows:

Code: Select all

0:000> !dumpdomain
Assembly:           000001b574001e10 [r41a5l4k, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b573c41c40
SecurityDescriptor: 000001b57854fb40
  Module Name
00007ffc1ef2ca90            r41a5l4k, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly:           000001b578913870 [45zmcw1t, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b578785210
SecurityDescriptor: 000001b573aaf3c0
  Module Name
00007ffc1ef2dab0            45zmcw1t, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly:           000001b578913bd0 [5csacesy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b578783cc0
SecurityDescriptor: 000001b573aae6a0
  Module Name
00007ffc1ef2ead0            5csacesy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly:           000001b5788060b0 [aobzfiqi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b570088100
SecurityDescriptor: 000001b570083690
  Module Name
00007ffc1f180020            aobzfiqi, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly:           000001b578602960 [oeqvjqls, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b578603b00
SecurityDescriptor: 000001b56ea5d3c0
  Module Name
00007ffc1f181040            oeqvjqls, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly:           000001b573d39f10 [u0zn4olz, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]
ClassLoader:        000001b573fddde0
SecurityDescriptor: 000001b573d9a420
  Module Name
00007ffc1f182060            u0zn4olz, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null 
These assemblies all have random string names, a uniform version of 0.0.0.0, and no public key token—consistent with the characteristics of dynamically compiled assemblies.

Does this indicate that Interpretation mode does not fully disable dynamic assembly generation, but only suppresses its rapid growth?

Could these residual dynamic assemblies be related to the native GDI object accumulation and file mapping anomalies mentioned in Floor 1, further exacerbating memory drift?

Beyond StiCalculationMode.Interpretation and StiOptions.Engine.ReportCache.AllowGCCollect = true, are there any additional configuration items that can avoid the accumulation of anonymous assemblies?
Lech Kulikowski
Posts: 7587
Joined: Tue Mar 20, 2018 5:34 am

Re: [Question] Native Memory Accumulation & File Mapping Behavior during High-Volume Printing (Interpretation Mode)

Post by Lech Kulikowski »

Hello,

It looks like it should be fine. But there may be nuances in small details.

For example, subreports from external files where compilation is enabled.
To definitely rule this out, set StiOptions.Engine.ForceInterpretationMode = true;

We need a sample project that reproduces the issue in order to give any precise recommendations.

Thank you.
Post Reply