daxu
daxu

Reputation: 4074

Is this an undisposed item issue or Large Object Heap issue?

I am trying to work out why one of our site is using 2.3GB memory. From windbg, when I run !dumpheap -stat, I got this:

000007fe992ae8d8    39413     11489246 System.Byte[]
000007fe992abf40     8567     14995548 System.Char[]
000007fe994500b0    31763     31617136 System.Int32[]
000007fe9c7b4cf8  1221470     48858800 XXXXXXX.SearchService+SectorItem
000007fe9925ba30   219828     49646032 System.Object[]
000007fe992a46f0  4273039    264621916 System.String
0000000002a35c10     2214    923713198      Free
Total 6994094 objects
Fragmented blocks larger than 0.5 MB:
            Addr     Size      Followed by
000000010625ef50    1.2MB 00000001063982e0 System.Collections.Hashtable
00000001064c9ed0    4.4MB 0000000106932128 System.Object[]
0000000206a4ee48    0.6MB 0000000206ae0a10 System.String
0000000206d270a0    3.9MB 0000000207106058 Free
0000000305282098    0.8MB 000000030534d248 System.Xml.XmlElementListListener
00000003053c5ad0    0.9MB 00000003054a87c0 System.String
0000000406a8b0f0    1.9MB 0000000406c73f10 System.WeakReference
0000000406c7aac8    2.2MB 0000000406ea43a8 System.Byte[]
0000000406ef89a8    1.5MB 00000004070721d8 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.String, mscorlib],[System.DateTime, mscorlib]]
0000000407072208    1.2MB 00000004071a77c0 System.Threading.ThreadPoolWorkQueueThreadLocals
00000004073d1110   11.3MB 0000000407f1a7f8 Free

We can see that there are more than 900MB "Free" object and never got released from IIS memory (as I looked the chart for a couple of days). There are 2200 Free objects, if I do this:

!dumpheap -mt 0000000002a35c10

There are lots of Free Objects:

00000005310b8008 0000000002a35c10       30 Free
00000005310dce28 0000000002a35c10       30 Free
0000000531101a50 0000000002a35c10       30 Free
0000000531126870 0000000002a35c10       30 Free
000000053114c680 0000000002a35c10       30 Free
0000000531187ee8 0000000002a35c10       30 Free
00000005311c3538 0000000002a35c10       30 Free
00000005311fefe0 0000000002a35c10 18583286 Free
0000000532a5e3a0 0000000002a35c10  9499822 Free
0000000533383848 0000000002a35c10  9830638 Free
0000000533d98db8 0000000002a35c10 46462326 Free
0000000536a40d70 0000000002a35c10       30 Free
0000000536a6f300 0000000002a35c10 10549646 Free
00000005374cf138 0000000002a35c10 10246582 Free
0000000537ee4f98 0000000002a35c10 80664406 Free
000000053cccb570 0000000002a35c10 22118654 Free

According to this article: https://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/ Anything bigger than 85000bytes won't be recollected automatically. So can I conclude that we have some really large objects in memory (e.g. maybe a large dictionary) and never get removed by GC? So it is a LOH issue other than a memory leak issue?

If it is a LOH issue, does it make any difference if the large object is in Cache (so reused) or used in memory once? Will GC collect either of them?

Upvotes: 2

Views: 242

Answers (1)

Thomas Weller
Thomas Weller

Reputation: 59305

Anything bigger than 85000bytes won't be recollected automatically.

It will be collected, but it will not be included in the compaction of the GC heaps.

So can I conclude that we have some really large objects in memory [...]

Not from the given data. If two Free regions follow each other, they will be combined into a bigger one. So, a 9 MB Free region could potentially have been 1000 "small" objects of 9000 bytes each which were aligned in memory subsequently.

[...] and never get removed by GC?

They are already removed by the GC, because it's Free. These are not objects of type Free. It's really free from .NET point of view and it will be reused by the .NET framework when you create new objects.

However, that memory has not been returned from .NET back to the OS using a VirtualFree() call. Thus, from OS point of view, the memory is still in use.

So it is a LOH issue [...]

It's not possible to tell that without knowing the boundaries of the GC heaps. Try !eeheap to see where the generations start or use SOSEX' !dumpgen to dump a specific GC heap only to see if it contains Free objects.

[...] other than a memory leak issue?

It's not a memory leak, since the memory has been freed by the garbage collector. Your developers cannot do much to make .NET return that memory back to the OS. For some reason, .NET thinks it should keep the memory for later use.

does it make any difference if the large object is in Cache (so reused) or used in memory once?

If it's referenced by a cache, the object will not be garbage collected (if it's not a weak reference). You'll then not see Free objects any more but the real objects instead.

Will GC collect either of them?

The GC will collect objects that are not referenced and potentially collect objects that are referenced by weak references (which a cache might use).

Upvotes: 1

Related Questions