Reputation: 1607
I am working on debugging an application that seems to leak memory like crazy; most of it seems due to fragmentation from pinned objects(downloaded image data in a WriteableBitmap). However, I am not intentionally using GC.Handle or anything like it. All I do is store the data in a MemoryStream
, and reference it like that.
What operations pin data in memory, that don't explicitly say so? Also, how can I find what pinned it using WinDbg?
EDIT: Per request, here is a (slightly sanitized) output of one of a !GCRoot on a System.Int32 array adjacent to a large block of free memory. This is representative of all of the large free blocks.
EDIT 2: After spending time with my new friends WinDbg and SOS, I found that WriteableBitmaps
AND MemoryStream
objects, are both 'pinned', and should be allocated carefully to prevent memory fragmentation. Read the article from the accepted answer for an explanation as to why that needs to be done.
DOMAIN(1AC72358):HANDLE(Pinned):72c12f8:Root: 174c5e20(System.Object[])->
16533060(Project.ProjectParts.PartContainer)->
167fe554(Project.ProjectParts.Part.PartActivity)->
167d21d8(Project.ProjectParts.Sprites.Graphic)->
16770f28(System.Windows.Controls.Canvas)->
16770e1c(System.Windows.Controls.Canvas)->
16770ee4(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
1680e778(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16770f9c(System.Windows.Controls.Canvas)->
16819114(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819160(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16818df4(System.Windows.Controls.Canvas)->
16818e58(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819f10(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
168194c4(System.Windows.Controls.Canvas)->
16819528(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819574(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16819370(System.Windows.Controls.Image)->
21c82138(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
21c82184(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
168195dc(System.Windows.Media.Imaging.WriteableBitmap)->
21c7ce2c(System.Int32[])
DOMAIN(1AC72358):HANDLE(AsyncPinned):72c1dfc:Root: 166bae48(System.Threading.OverlappedData)->
1654d448(System.Threading.IOCompletionCallback)->
1654c29c(System.Net.Sockets.SocketAsyncEventArgs)->
1654bad4(System.Net.Sockets.Socket+StaticConnectAsyncState)->
1654ba40(System.Net.Sockets.SocketAsyncEventArgs)->
1654b684(System.ServiceModel.Channels.SocketConnectionInitiator+ConnectAsyncResult)->
1654b414(System.ServiceModel.Channels.ConnectionPoolHelper+EstablishConnectionAsyncResult)->
1654b3b0(System.ServiceModel.Channels.ClientFramingDuplexSessionChannel+OpenAsyncResult)->
1654b380(System.ServiceModel.Channels.CommunicationObject+OpenAsyncResult)->
1654b330(System.ServiceModel.Channels.CommunicationObject+OpenAsyncResult)->
1654b0f4(System.ServiceModel.Channels.ServiceChannel+SendAsyncResult)->
1654b070(System.ServiceModel.ClientBase`1+AsyncOperationContext[[Cassandra.Common.WCF.IAsyncWcfRequestProcessor, Cassandra.Common.Silverlight]])->
1654b05c(System.ComponentModel.AsyncOperation)->
1654b04c(Project.Common.IoC.InvokeAsyncCompletedEventRequestsArgs)->
1654afec(System.Action`1[[Project.Common.IoC.ProcessRequestsAsyncCompletedArgsEx, Project.Common.SL]])->
1654afc8(Project.Common.IoC.AsyncRequestDispatcherEx+<>c__DisplayClass1)->
1654afa0(Project.Common.IoC.NetResponseReceiver)->
1653408c(System.Action`2[[Cassandra.Common.ExceptionInfo, Cassandra.Common.Silverlight],[Cassandra.Common.ExceptionType, Cassandra.Common.Silverlight]])->
16533ffc(Project.ProjectParts.ILE.Services.EngineProxyService+<>c__DisplayClass5)->
16533fdc(System.Action`1[[Cassandra.Common.ReceivedResponses, Cassandra.Common.Silverlight]])->
16533fbc(Project.ProjectParts.ILE.Services.IEngineProxyExtensions+<>c__DisplayClass1`2[[Project.Services.RequestsAndResponses.ListMediaServersByTokenRequest, Project.Services.RequestsAndResponses.Silverlight],[Project.Services.RequestsAndResponses.ListInstitutionMediaServersResponse, Project.Services.RequestsAndResponses.Silverlight]])->
16533f9c(System.Action`1[[Project.Services.RequestsAndResponses.ListInstitutionMediaServersResponse, Project.Services.RequestsAndResponses.Silverlight]])->
1650a2a0(Project.ProjectParts.ILE.MainPage)->
1674ea0c(Project.ProjectParts.ActivityTimer)->
165330a4(Project.ProjectParts.PauseManager)->
165330bc(System.Collections.Generic.List`1[[Project.ProjectParts.IPausable, ActivityFramework]])->
166a8610(System.Object[])->
167ca858(Project.ProjectParts.ActivityTimer)->
167ca838(Project.ProjectParts.ActivityTimerEventHandler)->
16533060(Project.ProjectParts.PartContainer)->
167fe554(Project.ProjectParts.Part.PartActivity)->
167d21d8(Project.ProjectParts.Sprites.Graphic)->
16770f28(System.Windows.Controls.Canvas)->
16770e1c(System.Windows.Controls.Canvas)->
16770ee4(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
1680e778(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16770f9c(System.Windows.Controls.Canvas)->
16819114(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819160(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16818df4(System.Windows.Controls.Canvas)->
16818e58(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819f10(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
168194c4(System.Windows.Controls.Canvas)->
16819528(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
16819574(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
16819370(System.Windows.Controls.Image)->
21c82138(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
21c82184(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
168195dc(System.Windows.Media.Imaging.WriteableBitmap)->
21c7ce2c(System.Int32[])
DOMAIN(1AC72358):HANDLE(Pinned):72c2b18:Root: 21c7ce2c(System.Int32[])
Upvotes: 7
Views: 812
Reputation: 1
Pin is mechanism to hold Async or handlers in your controls to be "do not relocated in memory" while the operation is in progress or handler reference exists.
You should also check whether you have any handlers or Async operations such as WCF client or Http Web Service client open state, prior to leaving the control or view model or model. If any object is pinned when you exit the control, view model or model you will have memory leak for those.
Also keep in mind that if those object ends up to be more than 85.000bytes they end up to be in generation 2 which is not Garbage Collected until the application (domain) terminates.
If object is smaller than 85K and survives the GC for Generation 0. Its promoted to Generation 1, and when survive or is not released or something is holding its will be end its life to Generation 2, which in SL is not collected.
Also to note: if you release/allocate frequently those object will cause the memory to be fragmented. If your program requires to have continuous space in memory and there is no free block that big because of the fragmentation you will get out of memory exception.
Hope above helps.
Upvotes: 0
Reputation: 4247
Assuming silverlight works in the same way as the full .net framework, an object over 85k in size will pretty much never be garbage collected. http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
We broke up our large queue objects into an array of smaller queues which then allowed the data structure to be collected once they had shrunk back down to normal running size. Before this code change, once the queue had grown beyond the threshold the memory would never be released back to the OS.
Could this be what you are experiencing?
Upvotes: 1