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;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
...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();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
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.
}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!