Note that there are some explanatory texts on larger screens.

plurals
  1. PO.NET RegEx "Memory Leak" investigation
    primarykey
    data
    text
    <p>I recently looked into some .NET "memory leaks" (i.e. unexpected, lingering GC rooted objects) in a WinForms app. After loading and then closing a huge report, the memory usage did not drop as expected even after a couple of gen2 collections. Assuming that the reporting control was being kept alive by a stray event handler I cracked open WinDbg to see what was happening...</p> <p>Using WinDbg, the <code>!dumpheap -stat</code> command reported a large amount of memory was consumed by string instances. Further refining this down with the <code>!dumpheap -type System.String</code> command I found the culprit, a 90MB string used for the report, at address 03be7930. The last step was to invoke <code>!gcroot 03be7930</code> to see which object(s) were keeping it alive.</p> <p>My expectations were incorrect - it was not an unhooked event handler hanging onto the reporting control (and report string), but instead it was held on by a <code>System.Text.RegularExpressions.RegexInterpreter</code> instance, which itself is a descendant of a <code>System.Text.RegularExpressions.CachedCodeEntry</code>. Now, the caching of Regexs is (somewhat) common knowledge as this helps to reduce the overhead of having to recompile the Regex each time it is used. But what then does this have to do with keeping my string alive?</p> <p>Based on analysis using Reflector, it turns out that the input string is stored in the RegexInterpreter whenever a Regex method is called. The RegexInterpreter holds onto this string reference until a new string is fed into it by a subsequent Regex method invocation. I'd expect similar behaviour by hanging onto Regex.Match instances and perhaps others. The chain is something like this:</p> <ul> <li>Regex.Split, Regex.Match, Regex.Replace, etc <ul> <li>Regex.Run <ul> <li>RegexScanner.Scan (RegexScanner is the base class, RegexInterpreter is the subclass described above).</li> </ul></li> </ul></li> </ul> <p>The offending Regex is only used for reporting, rarely used, and therefore unlikely to be used again to clear out the existing report string. And even if the Regex was used at a later point, it would probably be processing another large report. This is a relatively significant problem and just plain feels dirty.</p> <p>All that said, I found a few options on how to resolve, or at least work around, this scenario. I'll let the community respond first and if no takers come forward I will fill in any gaps in a day or two.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload