{"id":23154,"date":"2004-12-19T18:09:00","date_gmt":"2004-12-19T18:09:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/maoni\/2004\/12\/19\/using-gc-efficiently-part-3\/"},"modified":"2021-10-04T16:38:33","modified_gmt":"2021-10-04T23:38:33","slug":"using-gc-efficiently-part-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/using-gc-efficiently-part-3\/","title":{"rendered":"Using GC Efficiently \u2013 Part 3"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">In this article I\u2019ll talk about pinning and weak references \u2013 stuff related to GC handles.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">(I was planning on talking about finalization in this part of the \u201cUsing GC Efficiently\u201d series but since I already covered it in pretty much detail in <\/font><A href=\"http:\/\/blogs.msdn.com\/maoni\/archive\/2004\/11\/04\/252697.aspx\"><font face=\"Verdana\" color=\"#0000ff\" size=\"2\">one of my previous blog entries<\/font><\/a><font face=\"Verdana\" size=\"2\"> I won\u2019t repeat it here. Feel free to ask if you have questions not answered by that entry.)<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><b><font size=\"2\"><font face=\"Verdana\">Pinning<\/font><\/font><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">In a way pinning is like finalization \u2013 both exist because we have to deal with native code. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">When do objects get pinned? In 3 situations:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Using of GCHandle of type GCHandleType.Pinned;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Using the \u201cfixed\u201d keyword in C# (and other languages might have similar things, I don\u2019t know);<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">3)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">During Interop, certain types of arguments get pinned by Interop (for example, to marshal LPWSTR as a String object, Interop pins the buffer for the duration of the call).<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">For small object heap,<span>&nbsp; <\/span>pinning is the only user scenario that could create fragmentation (by \u201cuser scenario\u201d I mean not by the runtime\/GC itself but rather from the user code). <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">For large object heap, pinning is no-op as large object heap is never compacted. But you should always pin it if you want it to be pinned. As I mentioned in my previous entry, LOH always being swept is an implementation detail.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">Creating fragmentation is never a good thing. It makes GC work a lot harder \u2013 instead of simply \u201csqueezing\u201d live objects together now it has to keep records of which live objects are pinned and try to fit objects in free spaces between pinned objects. With each release we are doing more work in mitigating issues created by fragmentated heaps.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Verdana\">So how do you determine how much fragmentation you have in your application? You can use the !dumpheap command in the SOS debugger extension and look for Free objects \u2013 \u201c<\/font><span>!dumpheap \u2013type Free \u2013stat<\/span><font face=\"Verdana\">\u201d will give you the summary of all Free objects. Generally if there\u2019s 10% or less fragmentation in the heap I wouldn\u2019t worry about it. So when you have a big heap don\u2019t panic if you see the absolute number of bytes of Free objects being high but is less than 10%. Looking at the objects after the Free objects could give you a clue who is pinning. <\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">When you do need to pin, here are some things to keep in mind:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Pinning for a short time is cheap.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">How short is \u201ca short time\u201d? Well, if there\u2019s no GC happening, pinning simply sets a bit in the<span>&nbsp; <\/span>object header and unpinning simply clears it. But when GC happens, we have to make sure to<span>&nbsp; <\/span>not move the pinned objects. So \u201cpinning for a short time\u201d means when GC doesn\u2019t notice this object was pinned. This in turn means when you pinned some objects, and before you unpin it there\u2019re not much, if any, allocations going on. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Pinning an older object is not as harmful as pinning a young object. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><font face=\"Verdana\">By \u201can older object\u201d I mean an object that has had the chance to migrate to Gen2 and being compacted into a relatively stable location.<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">3)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Creating pinned buffers that stay together instead of scattered around. This way you create fewer holes.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">A couple of examples of good techniques:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Allocate a pinned buffer in LOH and give out a chuck at a time. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">The downside is \u201cchucks\u201d are not objects and there are very few APIs that accept non objects.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Allocate a pool of small object buffers and hand them out when needed. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">For example, I have a pool of buffers, and method M takes a byte array which needs to be pinned. If the buffer is already in Gen2 it\u2019s ok to pin it. The idea is hopefully your method doesn\u2019t need to use the buffer for long so the buffer will be free in a Gen0 or Gen1 collection. When the buffer is not a Gen2 buffer you get a buffer from your buffer pool to use \u2013 all buffers in the buffer pool by now are most likely all in Gen2 anyway:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>void<\/span><span> M(<span>byte<\/span>[] b)<\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (GC.GetGeneration(b) == GC.MaxGeneration)<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>RealM(b);<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ GetBuffer will allocate one if no buffers <\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ are available in the buffer pool.<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>byte<\/span>[] TempBuffer = BufferPool.GetBuffer();<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>RealM(TempBuffer);<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>CopyBackToUserBuffer(TempBuffer, b);<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>BufferPool.Release(TempBuffer);<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><b><font size=\"2\"><font face=\"Verdana\">Weak References<\/font><\/font><\/b><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">How are weak references implemented?<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">A weak reference has a managed part and a native part. The managed part is the WeakReference class itself. In its constructor we ask to create a GC handle which is the native part of it \u2013 it inserts an entry in that AppDomain\u2019s handle table (note that GCHandle\u2019s are all created this way \u2013 they are just inserted as their respective types). The object that the weak reference refers to will die when there are no strong references point to it. Since the weak reference is a managed object itself, it will be freed like any other managed objects.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">This means if you have a very small object, let\u2019s say one DWORD field, the object will be 12 bytes (size of a mininal object). If you have a WeakReference which has an IntPtr and a bool field, and the GC handle which is a pointer size, you are paying more than the object size to refer to the object with a weak reference. So obviously you don\u2019t want to get into a situation where you are creating many weak references to refer to a small object. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">What are the uses of weak references?<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">1)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Keeping an object alive temporarily or clean up when an object gets collected.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">Why would you use weak references to watch objects to clean up, instead of using a finalizer? The advantage is that the object being watched isn\u2019t promoted like it would be if it had a finalizer; the disadvantage is that it\u2019s more expensive in terms of memory consumption and the clean up happens only when the user code checks on the object the weak reference points to being null.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">Option A):<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>class<\/span><span> A<\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>WeakReference _target;<span>&nbsp;&nbsp;&nbsp; <\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>MyObject Target<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>set<\/span> <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{ <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_target = <span>new<\/span> WeakReference(<span>value<\/span>); <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>get<\/span> <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;&nbsp;<\/span>Object o = _target.Target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (o != <span>null<\/span>)<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> o;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>else<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ my target has been GC&#8217;d &#8211; clean up<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Cleanup();<span>&nbsp;&nbsp;&nbsp; <\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> <span>null<\/span>;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>void<\/span> M()<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ target needs to be alive throughout this method.<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MyObject target = Target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (target == <span>null<\/span>)<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ target has been GC&#8217;d, don&#8217;t bother<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span>;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>else<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ always need target to be alive.<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>DoSomeWork(); <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>GC.KeepAlive(target);<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">Option B):<\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font size=\"2\"><span>class<\/span><span> A<\/span><\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>WeakReference _target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>MyObject ShortTemp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>MyObject Target<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>set<\/span> <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{ <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_target = <span>new<\/span> WeakReference(<span>value<\/span>); <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>get<\/span> <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Object o = _target.Target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (o != <span>null<\/span>)<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> o;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>else<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ my target has been GC&#8217;d &#8211; clean up<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Cleanup();<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span> <span>null<\/span>;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span><span>void<\/span> M()<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ target needs to be alive throughout this method.<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>MyObject target = Target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>ShortTemp = target;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>if<\/span> (target == <span>null<\/span>)<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ target has been GC&#8217;d, don&#8217;t bother<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>return<\/span>;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>else<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>{<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>\/\/ could assert that ShortTemp is not null.<\/span><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>DoSomeWork(); <\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">&nbsp;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span>&nbsp;&nbsp;<\/span>ShortTemp = <span>null<\/span>;<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\"><span>&nbsp;&nbsp;&nbsp; <\/span>}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">}<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font face=\"Verdana\" size=\"2\">2)<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Maintaining a cache.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">You can have an array of weak references:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><font size=\"2\">WeakReferencesToObjects WeakRefs[];<\/font><\/span><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">Where each item in the array references an object by a weak reference. Periodically we could go through this array and see which objects are dead and release the weak references for those objects. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">If we always get rid of the weak references when the objects they refer to are dead, the cache will be invalidated on each GC. <\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">If that\u2019s not sufficient for you, you can use a 2-level caching mechanism:<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font size=\"2\">\u00b7<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">Maintain a strong reference for the cached items for x amount of time;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><span><span><font size=\"2\">\u00b7<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Verdana\" size=\"2\">After x amount of time is up, convert the strong references to weak references. Weak references will be considered to be kicked out of the cache before strong references are considered.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"2\">You could have difference policies for the cache such as based on the times the cached items are queried \u2013 the ones that are queried less often are maintained by or converted to weak references; or based on the number of items in the cache, maintain weak references to the overflown items when the cache is bigger than a certain size. It all depends on your cache usage. Tuning caches is a whole other topic on its own \u2013 perhaps some day I will write about it.<\/font><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article I\u2019ll talk about pinning and weak references \u2013 stuff related to GC handles. &nbsp; (I was planning on talking about finalization in this part of the \u201cUsing GC Efficiently\u201d series but since I already covered it in pretty much detail in one of my previous blog entries I won\u2019t repeat it here. [&hellip;]<\/p>\n","protected":false},"author":3542,"featured_media":58792,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[3011,108],"class_list":["post-23154","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","tag-maoniposts","tag-performance"],"acf":[],"blog_post_summary":"<p>In this article I\u2019ll talk about pinning and weak references \u2013 stuff related to GC handles. &nbsp; (I was planning on talking about finalization in this part of the \u201cUsing GC Efficiently\u201d series but since I already covered it in pretty much detail in one of my previous blog entries I won\u2019t repeat it here. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/3542"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=23154"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/23154\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=23154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=23154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=23154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}