MANAGED DEBUGGING with WINDBG. Managed Heap. Part 3
Hi all,
This post is a continuation of MANAGED DEBUGGING with WINDBG. Managed Heap. Part 2.
MANAGED HEAP. Part 3
· We can take a look to which objects reference which objects in the heap:
We may see many objects in the heap that we think should have been cleaned up already. If they haven’t, it’s because they are still being referenced and GC can’t clean them.
We can look for references (“roots”) to an object. Let’s see this with a sample taken from an ASP.NET app:
0:000> !DumpHeap -stat
...
Statistics:
MT Count TotalSize Class Name
...
0ee10034 19218 7149096 ASP.lab3_1_aspx
...
Total 1748273 objects
0:000> !DumpHeap -mt 0ee10034
------------------------------
Heap 0
Address MT Size
...
0556b268 0ee10034 372
0556ccac 0ee10034 372
…
total 6524 objects
------------------------------
Heap 1
...
0:000> !GCRoot 0556b268
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 15 OSTHread 2c4
...
Scan Thread 13 OSTHread c4c
esi:Root:14f002dc(System.Web.HttpResponse)->
14f00194(System.Web.HttpContext)->
14f00a08(ASP.lab3_1_aspx)->
02b33d80(System.Web.Caching.Cache)->
02b33e60(System.Web.Caching.CacheMultiple)->
02b33e78(System.Object[])->
02b33e90(System.Web.Caching.CacheSingle)->
02b33f38(System.Web.Caching.CacheExpires)->
02b33f58(System.Object[])->
02b34878(System.Web.Caching.ExpiresBucket)->
10872ea0(System.Web.Caching.ExpiresPage[])->
094b5734(System.Web.Caching.ExpiresEntry[])->
0556bb94(System.Web.Caching.CacheEntry)->
0556bb74(System.Web.Caching.CacheItemRemovedCallback)->
0556b268(ASP.lab3_1_aspx)
Scan Thread 22 OSTHread 830
Scan Thread 23 OSTHread f7c
If we take a look to the source code of Lab3_1.aspx page, we can see why the page is being kept in memory by the Cache object:
public partial class Lab3_1 : System.Web.UI.Page
{
public void RemovedCallback(String k, Object v, System.Web.Caching.CacheItemRemovedReason r)
{
//do stuff when the item is removed
}
protected void Page_Load(object sender, EventArgs e)
{
UserInfo u = new UserInfo("James", "Dean", "MainStreet 21, NY");
Cache.Add(Guid.NewGuid().ToString(), u, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 5, 0), System.Web.Caching.CacheItemPriority.NotRemovable, new System.Web.Caching.CacheItemRemovedCallback(this.RemovedCallback) );
}
}
References can exist in several places:
1. In a registry of a thread:
0:022> !gcroot 0x14ef2a34
…
esi:Root: 14f002dc(System.Web.HttpResponse)->
…->
14ef2a34(ASP.lab3_1_aspx)
2. In the stack of a thread:
ESP:ef4f610:Root: 14f00194(System.Web.HttpContext)->
… ->
14ef2a34(ASP.lab3_1_aspx)
3. Within a GCHandle.
Different kind of handles can reference our objects:
- Strong Handles: they keep the object they point to alive until the handle is explicitly freed. Typically a static variable.
DOMAIN(001CAFF8):HANDLE(Strong):284118c:Root: 02b35d3c(System.Threading._TimerCallback)->
… ->
14ef2a34(ASP.lab3_1_aspx)
- Pinned Handles: they are used to prevent the GC from moving an object during collection. Pinning objects can cause heap fragmentation.
DOMAIN(001CCE68):HANDLE(Pinned) …
- Weak Short Handles: they are non null as long as the object they reference is alive because of another Strong reference. They are null otherwise.
DOMAIN(001CCE68):HANDLE(WeakSh) …
- Weak Long Handles: they are non null as long as the object they reference hasn’t been reclaimed by the GC. It can be resurrected.
DOMAIN(001CCE68):HANDLE(WeakLn) …
The distinction between Weak Short and Weak Long comes from the finalization semantics: a Weak Short reference is null if the object can be freed, but a Weak Long reference still refers to the freachable object.
4. In an object ready for finalization.
The object is no longer in use but nobody called its Dispose method.
Finalizer queue:Root: …
5. As a member of an object found in 1, 2 or 3 above.
If our object is referenced by another one, it can’t be garbage collected. We should get rid of that reference or dispose the object that references ours.
…
14ef3914(System.Web.Caching.CacheEntry) ->
14ef38f4(System.Web.Caching.CacheItemRemovedCallback) ->
14ef2a34(ASP.lab3_1_aspx)
If there is a live reference to an object, that object is said to be strongly rooted. .NET also introduces the notion of weakly rooted references. A weak reference provides a way for programmers to indicate to the GC that they want to be able to access an object, but they don't want to prevent the object from being collected. Such an object is available until it is collected by the GC. For example, you could allocate a large object, and rather than fully deleting and collecting the object, you could hold onto it for possible reuse, as long as there is no memory pressure to clean up the managed heap. Thus, weak references behave somewhat like a cache.
· We can calculate the size of an object:
We can see the size of an object including its child objects. For instance, to determine how much an ASP.NET app is caching, we can do the following:
0:028> !Name2EE * System.Web.Caching.Cache
...
--------------------------------------
Module: 6638c000 (System.Web.dll)
Token: 0x020000f7
MethodTable: 6639d878
EEClass: 6639d808
Name: System.Web.Caching.Cache
--------------------------------------
...
0:028> !DumpHeap -mt 6639d878
------------------------------
Heap 0
Address MT Size
046b9198 6639d878 12
total 1 objects
------------------------------
Heap 1
Address MT Size
total 0 objects
------------------------------
total 1 objects
Statistics:
MT Count TotalSize Class Name
6639d878 1 12 System.Web.Caching.Cache
Total 1 objects
0:028> !ObjSize 046b9198
sizeof(046b9198) = 319128 ( 0x4de98) bytes (System.Web.Caching.Cache)
Next post: MANAGED DEBUGGING with WINDBG. Managed Heap. Part 4.
Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.
Regards,
Alex (Alejandro Campos Magencio)