Significant Garbage Collector Changes in .NET 4.6.2

Maoni Stephens

Maoni Stephens - Main GC Developer

In this blog entry, we would like to discuss some significant changes that were made in the .NET 4.6.x garbage collector (GC).  We encourage you to get the latest version, 4.6.2.

Our main GC developer, Maoni Stephens wrote up a description of the enhancements that were delivered with the 4.6.2 framework. These changes were made in order to improve performance of the framework and to allow the garbage collector to operator more efficiently.

Make the Pinning Promotion More Efficient

In previous versions of the .NET Framework when an object reported as pinned survived, we couldn’t move that object and the adjacent live objects. Since we tend to leave pins in ephemeral generations (so you can use the free spaces between them sooner), this means we needed to scan them when performing ephemeral collections. If many other objects right around the pinned objects survived collection also then the ephemeral collection time could be higher than desired. Starting with version 4.6.2, this limitation was lifted so we could compact away the adjacent live objects around pinned objects. In testing, we saw dramatic improvements of ephemeral collection time in scenarios where GC was artificially pinning a lot of objects.

In the Before pic, the 2 non pinned objects get compacted away but the non pinned object next to the pinned object stays in gen0.

Inefficient Pinning Promotion

In 4.6.x this limitation was lifted so we could compact away the adjacent live objects around them. We saw dramatic improvements of ephemeral collection time in scenarios where GC was artificially pinning a lot of objects. In the After pic, we can see that the non pinned object next to pinned gets compacted away:

Optimized Pinning Promotion

When you pin a lot, such as when IO operations last for a long time and you observe long ephemeral GC pauses, you would very likely benefit from this change.

Using Free Space in Gen2 More Efficiently

In prior versions of the framework we used a first fit approach when we were compacting gen1 survivors into gen2 free list, which meant the GC discarded spaces that could not be used. This technique led to wasted spaces in memory.

Inefficient use of Gen2 Free Space

In the Before pic, we see that F0 disappeared because it was too small to fit S. We were able to compact S into F1 and part of F1 remains (for further compaction from gen1).

To improve on this and utilize memory more efficiently, we introduced a bucketed free list where we threaded left over free spaces into their respective bucket. We had to be very careful of the usage in the smallest bucket as there could be many of them. We also worked on a policy of which bucket to try as we didn’t want to lengthen the gen1 collection time much by spending more time in searching for a usable free space. We want to stay doing background GCs as much as possible in order to be more efficient at consuming free spaces.

More Efficient use of Gen2

In the After pic F0 remains on the free list and can be used for further compaction from gen1. And we try to fit S into F1 right away.

If you observe your gen2 memory increasing, one reason could be that we ran out of items on the free list.  Consequently, promoting gen1 survivors would require an increase in gen2 size.  For scenarios that are helped by this change you would see gen2 size increase much less quickly and we can accommodate more gen1 collections for every gen2 collection. This also means you would see blocking gen2s triggered less frequently because when the heap gets too big which causes the memory load to be too high we would do a blocking gen2 to compact.  In our tests, we have observed first party scenarios where the ratio of gen1 collections to gen2 collections increased from 20 to 1 to more than 200 gen1 collections for every gen2 collection.


If you were running into situations described above, you should definitely try out .NET 4.6.2 to benefit from these enhancements in the garbage collector.

Comments (14)
  1. Hassan Hashemi says:

    Great, thanks for sharing this piece.

  2. Dave says:

    Are these changes included in the Core CLR too?

  3. Digitalnut says:

    Just download .Net 4.6.2 Dev version and using VS 2015 tried to upgrade a project from 4.5.2 to 4.6.2. VS 2015 hangs after clicking “Yes” to “Target Framework Change”. Waited 2-3 minutes and had to restart VS.

  4. Just downloaded V4.6.2 Dev version and tried to upgrade a project. Using VS 2015 (Update 3), when I change the “Target framework” from 4.5.2 to 4.6.2 and clicking “Yes” on the “Target Framework Change” dialog, VS hangs. I waited a few minutes and had force close VS.

    1. I’ll see if I can find someone to help you.

    2. @DigitalNutcase

      Can you help log an issue at The issue maybe specific to your project/machine as I can’t repro the case.

      Vivek Mishra

  5. Thorn says:

    I don’t have any problem with GC! I have problem with mem allocation itself: MS cannot make things properly and even working in virtual machine, my program still bumps to problem “cannot allocate more than 2 gig!”. And this is on PC with 16GB RAM! Don’t tell me why that sh!t doesn’t work – it’s enough to say IT DOESN’T WORK. Period.

  6. Thorn says:

    Blah-blah, GC is cool, AND NOT EVEN ONE LINK TO DOWNLOAD. MS completely degraded in quality? Hey, dinos, you live in INTERNET era! Where is your links???

    1. The 4.6.2 framework should have been offered as a Windows update for your machine. You can grab the web installer from

      1. Smoozi says:

        I have .NET 4.6.2 since July 2016. In Jan 2017 we read article “how cool GC is in .NET 4.6.2”. Is it new game of MS “guess which .NET you have installed”? (despite the critics when MS messed up numeration since v.4.0)
        I’m upset of MS clowns who cannot put things properly. If they have NEW GC, why not to have new .NET?!! 4.6.3 or 4.7, whatever….
        And of course I won’t allow any “web updates” run on my production machine – I need offline installer.

        1. No APIs were changed in the 4.6.2 release with regards to the GC. By semantic versioning rules, its only a patch release and should only have the patch version number incremented.

          There is an offline installer available for 4.6.2 here:

  7. Learn to research says:

    @Thorn You might want to checkout on how to enable allocating arrays more then 2gb in size

Comments are closed.

Skip to main content