2015-08-20 8 views
10

होने से कचरा संग्रह को रोकने के लिए प्रतीत होता है हम वर्तमान में काफी बड़े WPF आधारित विंडोज एप्लिकेशन बनाने में मदद के लिए ReactiveUI का उपयोग कर रहे हैं। सब ठीक चल रहे थे, जब तक हमने पाया कि हमारा आवेदन बड़ी मात्रा में स्मृति का उपभोग कर रहा था ... मूल रूप से हमारे सभी विचार, दृश्य-मॉडल और मॉडल कचरा नहीं जा रहे थे।रिएक्टिवयूआई बाइंडिंग

जेट ब्रेन डॉटमेमरी जैसे मेमोरी प्रोफाइलर्स की जानकारी के आधार पर, ReactiveUI प्राथमिक अपराधी प्रतीत होता है। विशेष रूप से The ReactiveUI बाइंडिंग्स हैं जिन्हें हम अपने विचारों में कॉन्फ़िगर कर रहे हैं, भले ही हम सर्वोत्तम प्रथाओं का उपयोग कर रहे हों और यह सुनिश्चित कर लें कि दृश्य निष्क्रिय होने पर सभी बाइंडिंग का निपटारा किया गया हो।

निम्नलिखित एक विचार का नमूना है जिसे हम बना रहे हैं। किसी भी विचार के रूप में जहां हम गलत जा रहे हैं, की सराहना की जाएगी।

public partial class RunbookInputsView : IViewFor<RunbookInputsViewModel> 
{ 
    public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
     "ViewModel", typeof(RunbookInputsViewModel), typeof(RunbookInputsView)); 

    public RunbookInputsView() 
    { 
     InitializeComponent(); 

     this.WhenActivated(d => 
     { 
      d(this.OneWayBind(ViewModel, vm => vm.AddInput, v => v.AddInput.Command));     
      d(this.OneWayBind(ViewModel, vm => vm.Inputs, v => v.Inputs.ItemsSource)); 
     }); 
    } 

    object IViewFor.ViewModel 
    { 
     get { return ViewModel; } 
     set { ViewModel = (RunbookInputsViewModel)value; } 
    } 

    public RunbookInputsViewModel ViewModel 
    { 
     get { return (RunbookInputsViewModel) GetValue(ViewModelProperty); } 
     set { SetValue(ViewModelProperty, value); } 
    } 
} 
+1

आप पुष्टि की है कि छोड़ना तर्क निष्पादित हो रहा है है 'जोड़ने घ प्रयास करें (डिस्पोजेबल। क्रिएट (() => System.Diagnostics.Debug.WriteLine ("DEACTIVATED"))) 'आपके' WhenActivated 'कॉल में से एक को –

+0

ब्रेकपॉइंट्स का उपयोग करके ऐसा लगता है कि प्रतिक्रियाशील बाइंडिंग का सही ढंग से निपटान किया जा रहा है। –

+0

मेरी जांच अब CreateDerivedCollection और लैम्ब्डा के उपयोग पर केंद्रित है जिसका उपयोग व्युत्पन्न संग्रह के लिए नए आइटम का चयन करने के लिए किया जाता है। ऐसा लगता है कि जब लैम्ब्डा मेरी कक्षा के सदस्यों का संदर्भ दे रहा है तो मेरे पास स्मृति समस्याएं हैं। निम्नलिखित लगता है ठीक: 'source.CreateDerivedCollection (x => ViewModel (x));' लेकिन इस समस्या है लगता है: 'source.CreateDerivedCollection (x => ViewModel (एक्स, this.Something)); ' –

उत्तर

1

प्रश्न से यह कहना मुश्किल है कि रिसाव कहां से आ रहा है। रिसाव थोड़ी देर के लिए होता है, तो windbg (Debugging Tools For Windows का हिस्सा) के साथ प्रक्रिया को देते हैं (नोट:। आप x86 या x64 इस के लिए निर्माण करने के लिए काम करने के लिए आवश्यकता हो सकती है)

एक बार जब आप संलग्न किया है, की स्थापना की आदेशों दर्ज करके .net डिबगिंग के लिए:

.symfix 
sxe clr 
sxd av 
.loadby sos clr 

फिर आप !dumpheap -stat का उपयोग प्रत्येक प्रकार की स्मृति उपयोग पाने के लिए कर सकते हैं। यह निम्न स्वरूप में उत्पादन का उत्पादन: (मैं वर्ग नाम, और पठनीयता के लिए सूची छोटा कर दिया।)

0:012> !dumpheap -stat 
Statistics: 
       MT Count TotalSize Class Name 
000007fefa55d2e8  1   24 System.[...]TransportSinkProvider 
000007fefa55ce08  1   24 System.Run[...]rtSinkProvider 
000007fee7c32df0  1   24 System.LocalDataStoreHolder 
000007fee7c2ff78  1   24 System.Colle[...] 
000007fee7c2ece0  1   24 System.Resources.FastResourceComparer 
000007fee7c2ead0  1   24 System.Resources.ManifestBasedResourceGroveler 
000007fee7c2ea70  1   24 System.[...]eManagerMediator 
000007fee4cc1b70  4   1216 System.Xml.XmlDocument 

आप एक स्मृति रिसाव यह वह जगह है जहाँ आप लीक वस्तुओं देखेंगे है। (उनमें से बहुत से होना चाहिए।) एक बार जब आप लीकिंग की पहचान कर लेंगे, तो आप वास्तविक वस्तुओं की सूची प्राप्त करने के लिए !dumpheap -type कर सकते हैं। (इस उदाहरण के लिए मैं System.Xml.XmlDocument का उपयोग करेंगे। प्रकार का नाम केस संवेदी है, और पूरी तरह से योग्य होना चाहिए।)

0:012> !dumpheap -type System.Xml.XmlDocument 
     Address    MT  Size 
0000000002af9050 000007fee4cc1b70  304  
0000000002afa628 000007fee4cc1b70  304  
0000000002b0ea30 000007fee4cc1b70  304  
00000000037e2780 000007fee4cc1b70  304  

Statistics: 
       MT Count TotalSize Class Name 
000007fee4cc1b70  4   1216 System.Xml.XmlDocument 

आपकी सूची शायद एक बहुत बड़ा होगा, लेकिन संभावना का कहना है कि लीक से किसी यादृच्छिक उदाहरण प्रकार कुछ आप में रुचि रखते हैं हो जाएगा हम उन पतों में से एक पर एक !do करते हैं, हम उत्पादन है कि इस तरह दिखता है मिल जाएगा:।

0:012> !do 2af9050 
Name:  System.Xml.XmlDocument 
MethodTable: 000007fee4cc1b70 
EEClass:  000007fee4ae7f00 
Size:  304(0x130) bytes 
File:  C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll 
Fields: 
       MT Field Offset     Type VT  Attr   Value Name 
000007fee4cc2b40 40004fc  8 System.Xml.XmlNode 0 instance 0000000000000000 parentNode 
000007fee4cc2258 400050a  10 ...XmlImplementation 0 instance 0000000002af9180 implementation 
000007fee4cc22f0 400050b  18 ....Xml.DomNameTable 0 instance 0000000002af92e0 domNameTable 
[Entries removed for clarity] 
000007fee4cc26f0 400052f  108 ...m.Xml.XmlResolver 0 instance 0000000000000000 resolver 
000007fee7c18c48 4000530  126  System.Boolean 1 instance    0 bSetResolver 
000007fee7c113e8 4000531  110  System.Object 0 instance 0000000002af9788 objLock 
000007fee4cc11b0 4000532  118 ....Xml.XmlAttribute 0 instance 0000000000000000 namespaceXml 

आप में सूचीबद्ध वस्तुओं से किसी के साथ !do उपयोग कर सकते हैं अधिक जानकारी के लिए टेबल। System.String और System.Boolean जैसे प्रकार उनके वास्तविक मूल्यों को थूक देंगे। यदि यह उस ऑब्जेक्ट से स्पष्ट नहीं है जहां इसे बनाया गया था, तो अगले चरण की संभावना हमारे ऑब्जेक्ट्स के संदर्भों को खोजने के लिए !gcroot -nostacks का उपयोग करना होगा।

0:012> !gcroot -nostacks 2af9050 
HandleTable: 
    00000000006117d8 (pinned handle) 
    -> 0000000012a55748 System.Object[] 
    -> 0000000002af9050 System.Xml.XmlDocument 

Found 1 unique roots (run '!GCRoot -all' to see all roots). 

काफी हद तक अधिक आदेश हैं, और यह पहले से ही बहुत लंबा है। !help कमांड एक अच्छी सूची प्रदान करता है। (उनमें से किसी का उपयोग करने के लिए आपको ! साथ आदेश उपसर्ग नहीं करनी !help [command] एक विशिष्ट आदेश के बारे में विस्तृत जानकारी देता है उदाहरण !help dumpobj के लिए:।।?

0:012> !help dumpobj 
------------------------------------------------------------------------------- 
!DumpObj [-nofields] <object address> 

This command allows you to examine the fields of an object, as well as learn 
important properties of the object such as the EEClass, the MethodTable, and 
the size. 

You might find an object pointer by running !DumpStackObjects and choosing 
from the resultant list. Here is a simple object: 

    0:000> !DumpObj a79d40 
    Name: Customer 
    MethodTable: 009038ec 
    EEClass: 03ee1b84 
    Size: 20(0x14) bytes 
    (C:\pub\unittest.exe) 
    Fields: 
      MT Field Offset     Type VT  Attr Value Name 
    009038ec 4000008  4    Customer 0 instance 00a79ce4 name 
    009038ec 4000009  8     Bank 0 instance 00a79d2c bank 

Note that fields of type Customer and Bank are themselves objects, and you can 
run !DumpObj on them too. You could look at the field directly in memory using 
the offset given. "dd a79d40+8 l1" would allow you to look at the bank field 
directly. Be careful about using this to set memory breakpoints, since objects 
can move around in the garbage collected heap. 

What else can you do with an object? You might run !GCRoot, to determine what 
roots are keeping it alive. Or you can find all objects of that type with 
"!DumpHeap -type Customer". 

The column VT contains the value 1 if the field is a valuetype structure, and 
0 if the field contains a pointer to another object. For valuetypes, you can 
take the MethodTable pointer in the MT column, and the Value and pass them to 
the command !DumpVC. 

The abbreviation !do can be used for brevity. 

The arguments in detail: 
-nofields:  do not print fields of the object, useful for objects like 
        String 
संबंधित मुद्दे