7

We discovered this issue when hosting a legacy COM component in our Out Of Browser Silverlight application, first thinking it was an issue with our COM component.

Narrowing it down to hosting the most basic COM component imaginable still had the memory leak, however. This COM component used for testing is written in .NET, and simply sends events back to the Silverlight application every time a timer fires. Each event contains a single string only.

When running the Silverlight application, the process memory usage keeps growing. Profilers show no increase in managed memory, indicating that there's a leak in the Silverlight runtime / COM implementation.

Has anyone else seen this issue, and if so, have you been able to work around it?

Edit: Repro project now available at http://bitbucket.org/freed/silverlight-com-leak

SoftMemes
  • 5,602
  • 4
  • 32
  • 61
  • Who is allocating the string? It may be the string memory being leaked. If the COM component is allocating the string, it must also free it. – Jeff Yates Nov 19 '10 at 15:56
  • In my test example, the COM component is implemented in .NET, and the string is just a plain managed string. I don't know how the legacy COM component allocates its strings, but the same component does not leak when hosted in .NET. – SoftMemes Nov 19 '10 at 16:54
  • Well, you convinced me. That wasn't hard, didn't have anything else to look at. You'll need Microsoft Support to chase down the interop bug, have your credit card ready. – Hans Passant Nov 19 '10 at 17:14
  • @Hans - I've posted a bug report on the Silverlight Forum (http://forums.silverlight.net/forums/p/210055/494295.aspx), hopefully I'll get some official feedback. – SoftMemes Nov 19 '10 at 17:35
  • @Freed: Can you please post the code? – Jeff Yates Nov 22 '10 at 15:10
  • Also, what profiler do you use? Is it just measuring .NET desktop framework managed memory rather than Silverlight's? Worth looking at. – Jeff Yates Nov 22 '10 at 15:12
  • Simple test project that reproduces the problem is now available at https://bitbucket.org/freed/silverlight-com-leak. I've been using the YourKit profiler, which gives a reliable breakdown of the Silverlight classes allocated. Leaving the application running for long enough also eventually crashes it with an OutOfMemoryException, so there's no doubt memory is leaking somewhere. – SoftMemes Nov 22 '10 at 21:03
  • @Freed: Cool. I'll take a look. This is fascinating. – Jeff Yates Nov 22 '10 at 22:15

4 Answers4

1

Looking at your code, the string you pass back & forth is (11 characters + terminating zero) = 24 bytes in unicode. In COM Automation, BSTR are used wich adds 4 bytes for the leading pointer (32-bit), and you multiply that by 10000, wich is 10000 * 28 = 280000 bytes.

It means every millisecond (the timer's value is 1) you will allocate a lot of memory, and in .NET a 280000 bytes chunk will probably be allocated in the large object heap (> 85000 bytes). The result of hitting hard on the LOH is most of the time... problems with memory, as seen here for example: Large Object Heap Fragmentation

This is maybe something you should check. One simple thing to test is to reduce the size of your BigMessage. You can also dive in deep with WinDBG: http://blogs.msdn.com/b/tess/archive/2008/08/21/debugging-silverlight-applications-with-windbg-and-sos-dll.aspx and check what's really going on under covers.

Community
  • 1
  • 1
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
0

Make sure the COM component is freeing any strings it allocates.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
  • The legacy component may have leaks itself, but the test COM component is using only managed memory... – SoftMemes Nov 19 '10 at 16:39
  • @Freed: That might be the case but the underlying architecture still has to allocate BSTRs and free BSTRs. There is still a COM boundary. My expectation is that due to some reference counting, these are not freed and are therefore being leaked. – Jeff Yates Nov 22 '10 at 15:06
  • Okay, after some investigation it would appear that the strings are supposed to be freed once marshalled into a System.String. Not sure if Silverlight does the same but I would expect it to. Without seeing the code, it will be hard to work this out - however, there are some points in your description that intrigue me, so the code would be really useful. – Jeff Yates Nov 22 '10 at 15:11
  • as now mentioned above, a test solution is available at https://bitbucket.org/freed/silverlight-com-leak. – SoftMemes Nov 22 '10 at 21:04
0

Not familiar with Silverlight, but another possible cause of interop headaches is event handling: http://www.codeproject.com/KB/cs/LingeringCOMObjects.aspx

hythlodayr
  • 2,377
  • 15
  • 23
  • Thank you, but we are only ever instantiating the COM component once, the leak is from events being triggered, not components being released and created. – SoftMemes Nov 19 '10 at 16:41
  • 1
    .NET will handle all of the COM events whether you want to or not. Which means native memory will linger until you've forced garbage collection. But if you've forced garbage collection and memory is still leaking, then it's probably some other issue. – hythlodayr Nov 19 '10 at 17:41
0

Could it be that there are native resources not garbage collected? Maybe this is one of the very few cases where calling GC.Collect may be of benefit. Interesting reading here

Just for test you could call GC.Collect a couple (or even three times) and see what happens (I can't believe I'm actually suggesting this...).

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Francesco De Vittori
  • 9,100
  • 6
  • 33
  • 43
  • Forcing GC does bring down the managed memory a bit, which is to be expected, but there's still a huge chunk of native memory that is not affected – SoftMemes Nov 19 '10 at 17:22