[SL4/5] Strange DataTemplate memory leak
-
Tuesday, April 19, 2011 8:04 AM
We have a huge application that uses Navigation heavily. We've noticed that when view is abandoned it is never collected by GC. In order to test the case, we've added explicit calls to GC.Collect/WaitForPendingFinalizers in Frame.Navigated handler. We've tested the scenario where user jumps between two views many times. Memory usage kept growing each time by ~1-2MB. So starting with 60 MB footprint we've ended up at 120 pretty soon. We've analyzed situation with windbg and it resulted in following (commands are in bold):
0:040> !DumpHeap -type TestApp.ProjectListViewModel
Address MT Size
11255378 047f72f8 80
11361ea4 047f72f8 80
113a62b0 047f72f8 80
115b274c 047f72f8 80
11688904 047f72f8 80
116b2528 047f72f8 80
11c277a8 047f72f8 80
1a31690c 047f72f8 80
...0:040> !gcroot 11255378
Scan Thread 17 OSTHread 9c8
...
Scan Thread 36 OSTHread 2dd4
DOMAIN(0539F770):HANDLE(Pinned):57212f8:Root: 11e9b1e0(System.Object[])->
10eae04c(System.Collections.Generic.Dictionary`2[[System.IntPtr, mscorlib],[System.Object, mscorlib]])->
12d7acf0(System.Collections.Generic.Dictionary`2+Entry[[System.IntPtr, mscorlib],[System.Object, mscorlib]][])->
1124bf7c(System.Windows.DataTemplate)->
1124663c(TestApp.ProjectListView)->
11255378(TestApp.ProjectListViewModel)0:040> !do 1124bf7c
Name: System.Windows.DataTemplate
MethodTable: 5aacf424
EEClass: 5a740598
Size: 48(0x30) bytes
File: c:\Program Files (x86)\Microsoft Silverlight\5.0.60401.0\System.Windows.dll
Fields:
MT Field Offset Type VT Attr Value Name
5aac53ac 4000434 4 ...eObjectSafeHandle 0 instance 1124bfb8 m_nativePtr
5aac5574 4000435 8 ... System.Windows]] 0 instance 00000000 _valueTable
794784ac 4000436 24 System.Boolean 1 instance 0 _propagateInheritanceChanged
5aac1da8 4000437 c ....DependencyObject 0 instance 00000000 _inheritanceParent
5aac591c 4000438 10 ...reTypeEventHelper 0 instance 1124bfac _coreTypeEventHelper
5aaa778c 4000439 14 ...angedEventHandler 0 instance 00000000 DPChanged
79458a44 400043a 18 System.EventHandler 0 instance 00000000 _inheritaneContextChanged
5aaa7bb8 400043c 1c ...bject, mscorlib]] 0 instance 00000000 _treeChildren
5aaa30b4 400043d 20 ...rnal.IManagedPeer 0 instance 00000000 _treeParent
7947fd34 400043b c ...flection.Assembly 0 shared static _executingAssembly
>> Domain:Value 1013df90:NotInit 0539f770:NotInit <<
5aaa3078 400058c 28 ....IManagedPeerBase 0 instance 1124663c _eventRoot
5aac56b4 400058b 15c ...ependencyProperty 0 shared static TemplateProperty
>> Domain:Value 1013df90:NotInit 0539f770:10f01098 <<
5aac56b4 400058d 160 ...ependencyProperty 0 shared static DataTypeProperty
>> Domain:Value 1013df90:NotInit 0539f770:10f01080 <<Apparently, The only thing that references view (and therefore viewmodel) is DataTemplate, and that's what prevents view/viewmodel from being collected. The DataTemplate instance in charge looks like it was abandoned (no tree children or parent set) but it still references view via its _eventRoot.
Then we went ahead and removed DataGridTemplateColumn typed columns from DataGrid that is part of ProjectListView and repeated windbg the same test. It showed single instance of ProjectListViewModel that actually has no references and apparently will be collected by GC next time.
This behavior was tested on 4.0.60129.0 and 5.0.60401.0 versions of Silverlight runtime (built for Silverlight 4 in both cases). Does it mean that problem with memory leak from inline templates is still present? Are there any feasible workarounds available or a ETA for this to be fixed?..
I will also try converting the solution to build for SL5 and will report back.
All Replies
-
Thursday, April 21, 2011 8:41 AM
Hi,
Could you provide a repro project so that we can test it?
Thanks.
Regards
-
Wednesday, April 18, 2012 11:25 AM
I am having the exact same problem.
It does not seem to be the inline datatemplate issue (because I have removed the inlines).

-
Thursday, April 19, 2012 9:10 AM
Ok so I went ahead and tried to replicate the problem in its simplest form. Here is what I found:
If I define a celltemplate like so:
<DataTemplate x:Name="SharedTemplate"> <Grid/> </DataTemplate>Yes that is correct, a pointless template.
Then I connect it to a GridView like so:
<telerik:GridViewDataColumn x:Name="CheckBoxColumn" Header="Shared" HeaderCellStyle="{StaticResource GridViewHeaderCellStyle1}" HeaderTextAlignment="Center" Width="2*" IsFilterable="True" DataMemberBinding="{Binding NodeDefinition.Shared}" EditTriggers="None" CellTemplate="{StaticResource SharedTemplate}"> </telerik:GridViewDataColumn>Then the leak occurs like so:

If you go back to the datatemplate and remove the <Grid/> the leak vanishes. This does not make any sense, other than the fact that Telerik is involved which is mose likely part of the problem. Those guys cannot produce proper anything.
-
Thursday, April 19, 2012 10:54 AM
Ok so I found a hack that compensates.
Basically you have to attach an eventhandler to the RadGridView's hosting control's Unloaded event containing this code:
foreach (var column in FileChildrenGrid.Columns) column.CellTemplate = null; var fake = new RadGridView(); fake.Columns.AddRange(FileChildrenGrid.Columns.Cast<object>().ToList());The thinking goes like this. As soon as you apply a CellTemplate to the RadGridView's DataColumn (maybe other GridViews/ItemsControls too?) the underlying Silverlight framework causes that leaky Style object (see above diagram) to point to the Column.
Getting rid of this leak requires 2 steps.
1.)Clear out all CellTemplates in RadGridView's Columns so that step 2 will work:
2.)We need to re-add those columns to a fake RadGridView without the CellTemplates which causes that leaky Style reference to go away somehow, allowing the original RadGridView to be collected.

