Overview
High memory use in a .Net application is usually the result of Common Language Runtime (CLR) objects growing in size continuously. When the application memory use grows to over 1.4GB in size, the next time the application tries to “New” an object it will hit a CLR exception of type System.OutOfMemoryException causing the application to crash. The CLR memory is not really “leaked” like it could be in a C program that uses malloc() to get a handle to a memory address and does not free it before going out of scope, causing the memory location to be unusable again in the lifetime of the program. All .Net memory allocations are managed by the CLR garbage collector, so it knows about the location and size. Luckily, these large objects can’t be hidden, and there are tools to analyze a .Net application to find collections that are 1) large in size and 2) continue growing throughout the lifetime of the process. In this article, we use these tools to find the source of a .Net application that continually grows in size or “leaks.”
Summary
The new release of the ACME RocketSled Desktop 5.0 process Org.ACME.RocketSledDesktop.exe climbs in memory usage in nine hours of continuous use. We need to investigate the process memory usage to determine which internal objects are consuming the memory. These investigative steps are meant to be a guide to where to further investigate the source code for the root cause. The development team will take these results and use them to focus on the resulting objects to fix the memory use issue.
Methodology
We take a snapshot of memory utilization during two different times while the application is running. Note that these two snapshots should both be after the application under test is already warmed up. Then, we use the tools below to narrow our focus to the CLR classes, then to the objects, and finally to the reference owners of the objects.
Tools
RocketSled is a managed application, so we suspect the memory usage is in the CLR Garbage Collected (GC) Heap. To analyze this, we use publicly available Microsoft tools Console Debugger (CDB) and Son of Strike (SOS). To get the process in a memory using state, we run a UI automation test script and save a process dump after about one hour and then again after about two hours. This can also be done with a live process instead of a dump, but the process dumps can be saved and debugged offline anytime in the future without interrupting the machine running the test. To learn how to use CDB and save process dumps, please read the document Orasi published titled Debugging Windows Crashes with Microsoft Debugging Tools – Tutorial.
Discoveries
The GC Heap was using about 53MB after the first hour and 57MB after the second hour, a small increase but on an upward trend like we expected. The objects consuming most of the heap are System.Byte[] and System.String as represented below at the two-hour mark. They are sorted and descending by size. We truncated this list with just these six rows, but the inclusive list adds up to 57MB.
MT |
Count |
TotalSize |
Class Name |
79ba4aa0 |
4,454 |
14,403,816 |
System.Byte[] |
79b9fb08 |
105,553 |
6,073,728 |
System.String |
79b56d84 |
41,728 |
1,911,032 |
System.Object[] |
79ba55d8 |
4,133 |
1,047,984 |
System.Collections.Hashtable+bucket[] |
58cfe3b4 |
10,845 |
902,836 |
System.Windows.EffectiveValueEntry[] |
56d13de4 |
16,712 |
742,912 |
System.Windows.ChildValueLookup[] |
The next step is to find out what is holding references to these objects. Many of these ACME-owned objects are used to store data and have String or Byte[] properties. Notice that the reference count of these is climbing between the first hour and second hour. If we look at data from a full nine-hour run, we can guess that that they would be much higher. For example 112 – 75 = 37 per hour. 9hrs * 37 = 333.
Objects (ACME) | Count 1hr | Count 2hrs |
1acd2a38(Org.ACME.WileE.CoyoteBannerModel)-> | 75 | 112 |
152e0d70(Org.ACME.ApplicationObjects.User)-> | 75 | 112 |
00db9010(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> | 75 | 111 |
00dd4cb8(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> | 75 | 111 |
1ac2df70(Org.ACME.WileE.CoyoteWorkspaceHost)-> | 75 | 111 |
00dc2e0c(Org.ACME.RocketSledShell.RocketSledShellView)-> | 75 | 111 |
152e4868(Org.ACME.CoyoteManagement.CoyoteModel)-> | 75 | 104 |
1ac2afcc(Org.ACME.WileE.CoyoteWorkspace)-> | 75 | 93 |
1ac2b024(Org.ACME.WileE.ComponentUtilizationServiceClient)-> | 75 | 86 |
Now, looking at the reference chain to System.Byte[], we find a very large list. Filtering by Org.ACME and sorting by the most common objects in the chain, we find a reasonably sized list.
Then, we go back and look at the raw output of the reference chain to System.Byte[] and find the most commonly occurring Org.ACME objects and determine that the closest reference to System.Byte[] in an ACME object is usually Org.ACME.CoyoteManagement.CoyoteModel, which we believe could be the object that is being held in memory causing the memory usage. Also, on the top of the chain is what appears to be a timer event, System.Windows.Media.Animation.TimeManager, not a direct call from an explicit user action. We recommend that development look at the reference chain below and determine in the source code where Org.ACME.CoyoteManagement.CoyoteModel and the other ACME objects are being created and disposed and inspect them to make sure they are being properly disposed. Here is one of many of the above mentioned reference chains.
Common Reference Chain to System.Byte[]
ebx:Root: 00dc5d50(System.Windows.Media.Animation.TimeManager)-> 00dc5784(System.Windows.Media.MediaContext)-> 00dc591c(System.Collections.Generic.Dictionary`2[[System.Windows.Media.ICompositionTarget, PresentationCore],[System.Object, mscorlib]])-> 00ea9468(System.Collections.Generic.Dictionary`2+Entry[[System.Windows.Media.ICompositionTarget, PresentationCore],[System.Object, mscorlib]][])-> 00ea91f4(System.Windows.Interop.HwndTarget)-> 00db9010(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> 00dc2e0c(Org.ACME.RocketSledShell.RocketSledShellView)-> 00dd4cb8(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> 00ea652c(System.Windows.Controls.TextBlock)-> 00ea63b0(System.Windows.Controls.StackPanel)-> 00e61288(System.Windows.Controls.StackPanel)-> 00e62944(System.Windows.Controls.UIElementCollection)-> 00e62958(System.Windows.Media.VisualCollection)-> 00ea64b8(System.Object[])-> 00ea11f0(System.Windows.Controls.StackPanel)-> 00ea1498(System.Windows.Controls.UIElementCollection)-> 00ea14ac(System.Windows.Media.VisualCollection)-> 00ea3710(System.Object[])-> 00ea15d4(System.Windows.Controls.Image)-> 01619384(System.Windows.EffectiveValueEntry[])-> 0100910c(System.Windows.Automation.Peers.ImageAutomationPeer)-> 01008b00(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 01008a90(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1cdec464(System.Collections.Generic.List`1[[System.Windows.Automation.Peers.AutomationPeer, PresentationCore]])-> 1cdec47c(System.Object[])-> 155e5b08(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1cdecf28(System.Collections.Generic.List`1[[System.Windows.Automation.Peers.AutomationPeer, PresentationCore]])-> 1cdecf60(System.Object[])-> 1b062404(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1ac2df70(Org.ACME.WileE.CoyoteWorkspaceHost)-> 1ac2afcc(Org.ACME.WileE.CoyoteWorkspace)-> 1ac2b024(Org.ACME.WileE.ComponentUtilizationServiceClient)-> 152e0d70(Org.ACME.ApplicationObjects.User)-> 1adc5878(System.ComponentModel.PropertyChangedEventHandler)-> 1adc5860(System.Object[])-> 1adc5840(System.ComponentModel.PropertyChangedEventHandler)-> 1acd2a38(Org.ACME.WileE.CoyoteBannerModel)-> 152e4868(Org.ACME.CoyoteManagement.CoyoteModel)-> 1b513c40(System.ComponentModel.PropertyChangedEventHandler)-> 1b513c28(System.Object[])-> 1b513c08(System.ComponentModel.PropertyChangedEventHandler)-> 1b513bd8(MRPQL.MRPQLViewModel)-> 1b7aa524(MRPQL.MRPQLViewModel+ReadyEventHander)-> 1b513a38(MRPQL.MRPQLWindow)-> 1b528f64(System.Windows.Controls.Primitives.ToggleButton)-> 1b52ced0(System.Windows.EffectiveValueEntry[])-> 1b7a2320(System.Windows.ModifiedValue)-> 1b52ce54(System.Windows.Data.BindingExpression)-> 00dca6a8(MS.Internal.Data.DataBindEngine)-> 017ee558(System.Windows.Controls.ContentControl)-> 01ba64b8(System.Windows.EffectiveValueEntry[])-> 017ef238(System.Windows.DataTemplate)-> 017ef73c(System.Windows.TemplateContent)-> 017ef764(System.Windows.TemplateLoadData)-> 017ef7ec(System.Windows.TemplateContent+ServiceProviderWrapper)-> 017ef390(MS.Internal.Xaml.ServiceProviderContext)-> 017ef128(MS.Internal.Xaml.Context.ObjectWriterContext)-> 017ef164(MS.Internal.Xaml.Context.XamlContextStack`1[[MS.Internal.Xaml.Context.ObjectWriterFrame, System.Xaml]])-> 017ef1b8(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 0170deb4(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 0170def4(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 01437a6c(System.Windows.ResourceDictionary)-> 01437b94(System.Windows.ResourceDictionaryCollection)-> 01437bc0(System.Collections.Generic.List`1[[System.Windows.ResourceDictionary, PresentationFramework]])-> 016ae63c(System.Object[])-> 016cb3bc(System.Windows.ResourceDictionary)-> 016cdb4c(System.Windows.ResourceDictionaryCollection)-> 016cdb78(System.Collections.Generic.List`1[[System.Windows.ResourceDictionary, PresentationFramework]])-> 016cdccc(System.Object[])-> 016dcbd8(System.Windows.ResourceDictionary)-> 016f42f4(System.Windows.Baml2006.Baml2006Reader)-> 016f4544(System.Windows.Baml2006.BamlBinaryReader)-> 016f44fc(System.Windows.Baml2006.SharedStream)-> 016f4080(System.IO.MemoryStream)-> 027660c8(System.Byte[])
Steps to Analyze
We are providing some overview steps as a guide to performing this analysis on a similar memory use issue. The CLR objects and addresses will be different, but the methodology is the same.
Attach/Load Dump File
We have the two process dumps, and we can load the first one as follows.
cdb –z RocketSled1.dmp
Load SOS
Then, we need to load SOS to debug managed code. This command loads it from the same location as the CLR.
0:039> .loadby sos clr
EEHeap
We use “!eeheap -gc” to display a summary of the GC Heaps. We see that the “.NET CLR Memory\# Bytes in all Heaps” is up to 53,678,732 bytes or 53 MB.
0:039> !eeheap -gc Number of GC Heaps: 1 generation 0 starts at 0x1afbebac generation 1 starts at 0x1af7d708 generation 2 starts at 0x00d91000 ephemeral segment allocation context: none segment begin allocated size 00d90000 00d91000 01d8c260 0xffb260(16,757,344) 14eb0000 14eb1000 15e77644 0xfc6644(16,541,252) 1ab00000 1ab01000 1b477440 0x976440(9,921,600) Large object heap starts at 0x01d91000 segment begin allocated size 01d90000 01d91000 0278a5a8 0x9f95a8(10,458,536) Total Size: Size: 0x333128c (53,678,732) bytes. ------------------------------ GC Heap Size: Size: 0x333128c (53,678,732) bytes.
DumpHeap -stat
To find out more, we need to find out what type of objects are in the heap. From the “!dumpheap -stat” output we will pick the biggest contributor to the heap and see if we can find who owns those objects. In this case, it is the System.Byte[].
0:039> !dumpheap -stat total 0 objects Statistics: MT Count TotalSize Class Name … 79ba55d8 3052 798696 System.Collections.Hashtable+bucket[] 79b56d84 33474 1507180 System.Object[] 79b9fb08 83435 4888840 System.String 79ba4aa0 3722 10253640 System.Byte[] 00177578 8013 22125252 Free Total 509385 objects 0:039>
DumpHeap -mt
In order to find out who owns the System.Byte[], we first need to get some object addresses using “!dumpheap -mt” which will dump out all the object addresses for the specified type. There’s no real need to see all 30,000 addresses, so it’s okay to <ctrl><c> to interrupt the output.
0:039> !dumpheap -mt 79ba4aa0 Address MT Size 00d9ace4 79ba4aa0 524 00d9ea04 79ba4aa0 12 00d9f578 79ba4aa0 268 00d9fa98 79ba4aa0 28 00d9faec 79ba4aa0 140 … 0258a0b0 79ba4aa0 119632 025a7410 79ba4aa0 93808 025be290 79ba4aa0 93808 025d5110 79ba4aa0 148704 026a4988 79ba4aa0 93808 026bb808 79ba4aa0 93808 026d2688 79ba4aa0 148704 026f6b78 79ba4aa0 148704 0271b068 79ba4aa0 119632 027383c8 79ba4aa0 93808 0274f248 79ba4aa0 93808 027660c8 79ba4aa0 148704 0:039>
GCRoot
Now that we have some object addresses to look at, let’s see who owns the objects. We choose address 027660c8, because it is one of the largest in the list above. We could have chosen another such as 026d2688 or 026f6b78.
0:039> !gcroot 027660c8 Scan Thread 0 OSTHread 1b34 ESP:12f1b0:Root: 00d9d78c(System.Windows.Threading.DispatcherFrame)-> 00d9cc78(System.Windows.Threading.Dispatcher)-> 00db9968(System.Windows.Input.InputManager)-> 00db9f60(System.Windows.Input.StylusLogic)-> 00dba098(System.Collections.Generic.Dictionary`2[[System.Object, mscorlib],[System.Windows.Input.PenContexts, PresentationCore]])-> 00dba0e4(System.Collections.Generic.Dictionary`2+Entry[[System.Object, mscorlib],[System.Windows.Input.PenContexts, PresentationCore]][])-> 00ea8dc8(System.Windows.Interop.HwndSource)-> 00db9220(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> 00dc3080(Org.ACME.RocketSledShell.RocketSledShellView)-> 00dd4f4c(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> 00ea655c(System.Windows.Controls.TextBlock)->
We sort the output of “!gcroot 027660c8” and look at what has occurred most often containing “Org.ACME,” and the following is the result. This is easy to calculate by pasting into Excel and using a pivot table to group.
Call | Count |
1510d634(Org.ACME.WileE.CoyoteBannerModel)-> | 74 |
01924fdc(Org.ACME.ApplicationObjects.User)-> | 74 |
00dc3080(Org.ACME.RocketSledShell.RocketSledShellView)-> | 73 |
00dd4f4c(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> | 73 |
00db9220(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> | 73 |
019274c4(Org.ACME.CoyoteManagement.CoyoteModel)-> | 73 |
150661dc(Org.ACME.WileE.CoyoteWorkspaceHost)-> | 72 |
15062fac(Org.ACME.WileE.ComponentUtilizationServiceClient)-> | 54 |
15062f54(Org.ACME.WileE.CoyoteWorkspace)-> | 54 |
1aef9fd0(Org.ACME.WileE.CompositeView.JWPanel2)-> | 18 |
1ab24094(System.Collections.Generic.Dictionary`2+Entry[[Org.ACME.WileE.CompositeView.JWPanel, Org.ACME.WileE.CompositeView],[System.Int32, mscorlib]][])-> | 18 |
1521c4b8(System.Collections.Generic.Dictionary`2[[Org.ACME.WileE.CompositeView.JWPanel, Org.ACME.WileE.CompositeView],[System.Int32, mscorlib]])-> | 18 |
1521c384(Org.ACME.WileE.CompositeView.JWKeyHoleHost)-> | 18 |
00f6ecf4(Org.ACME.ApplicationObjects.Session)-> | 15 |
15abf01c(System.Collections.ObjectModel.ObservableCollection`1[[Org.ACME.Vitalsigns.Models.VitalSignsRecord, Org.ACME.Vitalsigns]])-> | 11 |
14fbf760(Org.ACME.WileE.Views.Help2SelectCoyoteView)-> | 2 |
00f25c20(Org.ACME.ApplicationObjects.OrganizationalUnit)-> | 1 |
DumpObj
First, we look at the object Org.ACME.WileE.CoyoteBannerModel at address 1510d634.
0:039> !do 1510d634 Name: Org.ACME.WileE.CoyoteBannerModel MethodTable: 034be4f8 EEClass: 0e8f1554 Size: 52(0x34) bytes File: C:\Program Files\ACME\WileE\Org.ACME.WileE.CoyoteBanner.dll Fields: MT Field Offset Type VT Attr Value Name 7aa055f4 4000001 4 ...angedEventHandler 0 instance 1510ddfc PropertyChanged 7aa02b58 4000002 8 ...fyPropertyChanged 0 instance 01ae41dc CoyoteContainerObject 7aa02b58 4000003 c ...fyPropertyChanged 0 instance 019274c4 CoyoteAlertsContainerObject 7aa02b58 4000004 10 ...fyPropertyChanged 0 instance 01924fdc userRoleContainerObject 79b9fb08 4000005 14 System.String 0 instance 150669b4 CoyoteRetrievalPropertyName 79b9fb08 4000006 18 System.String 0 instance 150669dc CoyoteAlertsRetrievalPropertyName 79b9fb08 4000007 1c System.String 0 instance 0109a408 userRoleRetrievalPropertyName 0cf2d24c 4000008 20 ...onObjects.Coyote 0 instance 1554cb60 activeCoyote 0cf238dc 4000009 24 ...licationObjects]] 0 instance 019274e8 CoyoteAlerts 04392fd4 400000a 28 ...ationObjects.Role 0 instance 019f446c userRole 79b90a5c 400000b 2c System.Int32 1 instance 28 propertyRetrievalFlags
ObjSize
Adding all the object sizes referencing Org.ACME.WileE.CoyoteBannerModel contribute 23MB of the 53MB GC Heap.
0:039> !objsize 1510d634 sizeof(1510d634) = 23323732 ( 0x163e454) bytes (Org.ACME.WileE.CoyoteBannerModel) 0:039>
DumpObj
Second, Org.ACME.ApplicationObjects.User.
0:039> !do 01924fdc Name: Org.ACME.ApplicationObjects.User MethodTable: 04392c34 EEClass: 042ac5f4 Size: 44(0x2c) bytes File: C:\Program Files\ACME\WileE\Org.ACME.ApplicationObjects.dll Fields: MT Field Offset Type VT Attr Value Name 7aa055f4 4000001 4 ...angedEventHandler 0 instance 1521d114 PropertyChanged 04392fd4 4000076 8 ...ationObjects.Role 0 instance 019f446c _currentRole 0d944964 4000077 c ...licationObjects]] 0 instance 019f4410 _roles 79b9fb08 4000078 10 System.String 0 instance 01923cb8 <FirstName>k__BackingField 79b9fb08 4000079 14 System.String 0 instance 01923b9c <LastName>k__BackingField 79b9fb08 400007a 18 System.String 0 instance 019244f4 <UserId>k__BackingField 79b9fb08 400007b 1c System.String 0 instance 01924ca8 <UnitNumber>k__BackingField 79ba6788 400007c 24 System.Boolean 1 instance 0 <IsAdmin>k__BackingField 79b9fb08 400007d 20 System.String 0 instance 01924b84 <UserNCID>k__BackingField
ObjSize
0:039> !objsize 01924fdc sizeof(01924fdc) = 23323732 ( 0x163e454) bytes (Org.ACME.ApplicationObjects.User)
DumpObj
Third, Org.ACME.RocketSledShell.RocketSledShellView.
0:039> !do 00dc3080 Name: Org.ACME.RocketSledShell.RocketSledShellView MethodTable: 0359005c EEClass: 03521f88 Size: 276(0x114) bytes File: C:\Program Files\ACME\WileE\Org.ACME.RocketSledShell.dll Fields: MT Field Offset Type VT Attr Value Name 58cf50f4 4000dbc 4 ...eading.Dispatcher 0 instance 00d9cc78 _dispatcher … 79ba6788 4000009 f3 System.Boolean 1 instance 1 _contentLoaded 04391818 400000a 4 ...er+ThreadDelegate 0 static 011b7de8 CS$<>9__CachedAnonymousMethodDelegate2 ObjSize 0:039> !objsize 00dc3080 sizeof(00dc3080) = 23323732 ( 0x163e454) bytes (Org.ACME.RocketSledShell.RocketSledShellView)
Attach/Load dump file
We now look at the same data after another hour of runtime. We can load the second process dump as follows:
cdb –z RocketSled2.dmp
SOS
Then we load SOS to debug managed code. This command loads it from the same location as the CLR.
0:039> .loadby sos clr
EEHeap
The heap has grown by 3MB in an hour. Not much, but if it continues this way, we have a leak.
0:000> !eeheap -gc Number of GC Heaps: 1 generation 0 starts at 0x1cb6b0c8 generation 1 starts at 0x1cae1000 generation 2 starts at 0x00d91000 ephemeral segment allocation context: none segment begin allocated size 00d90000 00d91000 01d725f4 0xfe15f4(16651764) 14eb0000 14eb1000 15b83da8 0xcd2da8(13446568) 1ab00000 1ab01000 1b82ae54 0xd29e54(13803092) 1cae0000 1cae1000 1ce05e48 0x324e48(3296840) Large object heap starts at 0x01d91000 segment begin allocated size 01d90000 01d91000 027a1418 0xa10418(10552344) Total Size: Size: 0x3713450 (57750608) bytes. ------------------------------ GC Heap Size: Size: 0x3713450 (57,750,608) bytes.
DumpHeap
0:035> !dumpheap -stat total 0 objects Statistics: MT Count TotalSize Class Name … 56d19340 21286 681152 System.Windows.Baml2006.KeyRecord 56d13de4 16712 742912 System.Windows.ChildValueLookup[] 58cfe3b4 10845 902836 System.Windows.EffectiveValueEntry[] 79ba55d8 4133 1047984 System.Collections.Hashtable+bucket[] 79b56d84 41728 1911032 System.Object[] 79b9fb08 105553 6073728 System.String 79ba4aa0 4454 14403816 System.Byte[] 00177578 3787 15291084 Free Total 674273 objects
DumpHeap -mt
This will be similar output to the first hour so not including output here.
GCRoot
Now that we have some object addresses to look at, let’s see who owns the objects.
0:039> !gcroot 027660c8
References for these objects have climbed from ~74 to ~112.
Call | Count |
1acd2a38(Org.ACME.WileE.CoyoteBannerModel)-> | 112 |
152e0d70(Org.ACME.ApplicationObjects.User)-> | 112 |
00db9010(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> | 111 |
00dd4cb8(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> | 111 |
1ac2df70(Org.ACME.WileE.CoyoteWorkspaceHost)-> | 111 |
00dc2e0c(Org.ACME.RocketSledShell.RocketSledShellView)-> | 111 |
152e4868(Org.ACME.CoyoteManagement.CoyoteModel)-> | 104 |
1ac2afcc(Org.ACME.WileE.CoyoteWorkspace)-> | 93 |
1ac2b024(Org.ACME.WileE.ComponentUtilizationServiceClient)-> | 86 |
1ae04444(System.Collections.Generic.Dictionary`2[[Org.ACME.WileE.CompositeView.JWPanel, Org.ACME.WileE.CompositeView],[System.Int32, mscorlib]])-> | 25 |
1adc4928(Org.ACME.WileE.CompositeView.JWPanelHost2)-> | 25 |
1ae06130(System.Collections.Generic.Dictionary`2+Entry[[Org.ACME.WileE.CompositeView.JWPanel, Org.ACME.WileE.CompositeView],[System.Int32, mscorlib]][])-> | 25 |
1abdaba8(Org.ACME.WileE.CompositeView.JWPanel2)-> | 25 |
00f6e494(Org.ACME.ApplicationObjects.Session)-> | 24 |
1af92194(System.Collections.ObjectModel.ObservableCollection`1[[Org.ACME.Vitalsigns.Models.VitalSignsRecord, Org.ACME.Vitalsigns]])-> | 11 |
1adc56c0(Org.ACME.WileE.WorkspaceBase+GetPanelCountEventHandler)-> | 7 |
ObjSize
0:035> !objsize 1acd2a38 sizeof(1acd2a38) = 33590192 ( 0x2008bb0) bytes (Org.ACME.WileE.CoyoteBannerModel) 0:035> !objsize 152e0d70 sizeof(152e0d70) = 33590192 ( 0x2008bb0) bytes (Org.ACME.ApplicationObjects.User) 0:035> !objsize 00dc2e0c sizeof(00dc2e0c) = 33590192 ( 0x2008bb0) bytes (Org.ACME.RocketSledShell.RocketSledShellView)
Observation
We go back and look at the raw output of the reference chain to System.Byte[] and find the most commonly occurring Org.ACME objects and determine that the closest reference to System.Byte[] in an ACME object is usually Org.ACME.CoyoteManagement.CoyoteModel, which we believe could be the object that is being held in memory causing the memory usage. Also, on the top of the chain is what appears to be a timer event, System.Windows.Media.Animation.TimeManager, not a direct call from an explicit user action. We recommend that development look at the reference chain below and determine in the source code where Org.ACME.CoyoteManagement.CoyoteModel is being created and disposed and inspect it to make sure it is being properly disposed. Here is the above mentioned reference chain.
Common Reference Chain to System.Byte[]
ebx:Root: 00dc5d50(System.Windows.Media.Animation.TimeManager)-> 00dc5784(System.Windows.Media.MediaContext)-> 00dc591c(System.Collections.Generic.Dictionary`2[[System.Windows.Media.ICompositionTarget, PresentationCore],[System.Object, mscorlib]])-> 00ea9468(System.Collections.Generic.Dictionary`2+Entry[[System.Windows.Media.ICompositionTarget, PresentationCore],[System.Object, mscorlib]][])-> 00ea91f4(System.Windows.Interop.HwndTarget)-> 00db9010(Org.ACME.RocketSledDesktop.RocketSledDesktopWIndow)-> 00dc2e0c(Org.ACME.RocketSledShell.RocketSledShellView)-> 00dd4cb8(Org.ACME.WileE.Views.Authentication.AuthenticationView)-> 00ea652c(System.Windows.Controls.TextBlock)-> 00ea63b0(System.Windows.Controls.StackPanel)-> 00e61288(System.Windows.Controls.StackPanel)-> 00e62944(System.Windows.Controls.UIElementCollection)-> 00e62958(System.Windows.Media.VisualCollection)-> 00ea64b8(System.Object[])-> 00ea11f0(System.Windows.Controls.StackPanel)-> 00ea1498(System.Windows.Controls.UIElementCollection)-> 00ea14ac(System.Windows.Media.VisualCollection)-> 00ea3710(System.Object[])-> 00ea15d4(System.Windows.Controls.Image)-> 01619384(System.Windows.EffectiveValueEntry[])-> 0100910c(System.Windows.Automation.Peers.ImageAutomationPeer)-> 01008b00(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 01008a90(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1cdec464(System.Collections.Generic.List`1[[System.Windows.Automation.Peers.AutomationPeer, PresentationCore]])-> 1cdec47c(System.Object[])-> 155e5b08(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1cdecf28(System.Collections.Generic.List`1[[System.Windows.Automation.Peers.AutomationPeer, PresentationCore]])-> 1cdecf60(System.Object[])-> 1b062404(System.Windows.Automation.Peers.UserControlAutomationPeer)-> 1ac2df70(Org.ACME.WileE.CoyoteWorkspaceHost)-> 1ac2afcc(Org.ACME.WileE.CoyoteWorkspace)-> 1ac2b024(Org.ACME.WileE.ComponentUtilizationServiceClient)-> 152e0d70(Org.ACME.ApplicationObjects.User)-> 1adc5878(System.ComponentModel.PropertyChangedEventHandler)-> 1adc5860(System.Object[])-> 1adc5840(System.ComponentModel.PropertyChangedEventHandler)-> 1acd2a38(Org.ACME.WileE.CoyoteBannerModel)-> 152e4868(Org.ACME.CoyoteManagement.CoyoteModel)-> 1b513c40(System.ComponentModel.PropertyChangedEventHandler)-> 1b513c28(System.Object[])-> 1b513c08(System.ComponentModel.PropertyChangedEventHandler)-> 1b513bd8(MRPQL.MRPQLViewModel)-> 1b7aa524(MRPQL.MRPQLViewModel+ReadyEventHander)-> 1b513a38(MRPQL.MRPQLWindow)-> 1b528f64(System.Windows.Controls.Primitives.ToggleButton)-> 1b52ced0(System.Windows.EffectiveValueEntry[])-> 1b7a2320(System.Windows.ModifiedValue)-> 1b52ce54(System.Windows.Data.BindingExpression)-> 00dca6a8(MS.Internal.Data.DataBindEngine)-> 017ee558(System.Windows.Controls.ContentControl)-> 01ba64b8(System.Windows.EffectiveValueEntry[])-> 017ef238(System.Windows.DataTemplate)-> 017ef73c(System.Windows.TemplateContent)-> 017ef764(System.Windows.TemplateLoadData)-> 017ef7ec(System.Windows.TemplateContent+ServiceProviderWrapper)-> 017ef390(MS.Internal.Xaml.ServiceProviderContext)-> 017ef128(MS.Internal.Xaml.Context.ObjectWriterContext)-> 017ef164(MS.Internal.Xaml.Context.XamlContextStack`1[[MS.Internal.Xaml.Context.ObjectWriterFrame, System.Xaml]])-> 017ef1b8(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 0170deb4(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 0170def4(MS.Internal.Xaml.Context.ObjectWriterFrame)-> 01437a6c(System.Windows.ResourceDictionary)-> 01437b94(System.Windows.ResourceDictionaryCollection)-> 01437bc0(System.Collections.Generic.List`1[[System.Windows.ResourceDictionary, PresentationFramework]])-> 016ae63c(System.Object[])-> 016cb3bc(System.Windows.ResourceDictionary)-> 016cdb4c(System.Windows.ResourceDictionaryCollection)-> 016cdb78(System.Collections.Generic.List`1[[System.Windows.ResourceDictionary, PresentationFramework]])-> 016cdccc(System.Object[])-> 016dcbd8(System.Windows.ResourceDictionary)-> 016f42f4(System.Windows.Baml2006.Baml2006Reader)-> 016f4544(System.Windows.Baml2006.BamlBinaryReader)-> 016f44fc(System.Windows.Baml2006.SharedStream)-> 016f4080(System.IO.MemoryStream)-> 027660c8(System.Byte[])