Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Gen-0 collections happens more frequently on macOS #12717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
smoogipoo opened this issue May 20, 2019 · 9 comments · Fixed by dotnet/coreclr#24777
Closed

Gen-0 collections happens more frequently on macOS #12717

smoogipoo opened this issue May 20, 2019 · 9 comments · Fixed by dotnet/coreclr#24777
Milestone

Comments

@smoogipoo
Copy link

We've observed the GC running much more frequently on .NET Core 3.0 preview 5 than .NET Core 2.2.5 on macOS.

The data I provide may be replicated via the following benchmark:

[MemoryDiagnoser]
public class ConcurrentQueueBenchmarks
{
    [Benchmark]
    public ConcurrentQueue<int> Queue()
    {
        return new ConcurrentQueue<int>();
    }
}
Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
macOS (.NET Core 2.2.5) 96.63 ns 0.8469 ns 0.7922 ns 0.2441 - - 768 B
macOS (.NET Core 3.0-preview5) 278.4 ns 1.203 ns 1.066 ns 3.5210 - - 576 B
Windows (.NET Core 2.2.5) 104.2 ns 2.094 ns 1.958 ns 0.2440 - - 768 B
Windows (.NET Core 3.0-preview5) 97.15 ns 0.5990 ns 0.5002 ns 0.1836 - - 576 B
Ubuntu 18.04 (.NET Core 2.2.5) 113.8 ns 7.344 ns 21.42 ns 0.2440 - - 768 B
Ubuntu 18.04 (.NET Core 3.0-preview5) 93.64 ns 5.161 ns 15.22 ns 0.1836 - - 576 B

This is not only exhibited by ConcurrentQueue; for example, Lazy experiences a similar ~10x increase in Gen 0 collections per 1000 instances.

I'm unsure of how to debug this further (please let me know how to, if required) - going this deep into the CLR without memory profiling tools on macOS is outside of my area of expertise at the moment.

@stephentoub
Copy link
Member

cc: @Maoni0

@Maoni0
Copy link
Member

Maoni0 commented May 21, 2019

cc @sergiy-k, @Andy-MS
do we see the same thing on Windows and Linux? it would be a lot easier to debug there (especially if we can repro this on windows).

@smoogipoo
Copy link
Author

This does not happen on Ubuntu 18.04 (added results to the OP) nor Windows.

@ghost
Copy link

ghost commented May 22, 2019

Can confirm that on windows and linux, there is a decrease in gen0 collections with ConcurrentQueue<int>, and a very small increase for object or Lazy<int>. Testing with:

using System;
using System.Collections.Concurrent;

class Program
{
    static void Main(string[] args)
    {
        object o;
        for (int i = 0; i < 100_000_000; i++)
        {
            o = new Lazy<int>(); // fill in your type here
        }

        for (int gen = 0; gen <= 2; gen++)
        {
            Console.WriteLine($"Gen {gen}: {GC.CollectionCount(gen)}");
        }
    }
}

(Building in debug mode, otherwise the code is optimized away for object; though ConcurrentQueue and Lazy<int> seem the same either way.)
Do we have any macs to test on?

@smoogipoo
Copy link
Author

smoogipoo commented May 22, 2019

@Andy-MS on mac I get:

With Lazy:

.NET Core 2.2.5:
Gen 0: 2288
Gen 1: 0
Gen 2: 0

.NET Core 3.0:
Gen 0: 44067
Gen 1: 0
Gen 2: 0

With ConcurrentQueue:

.NET Core 2.2.5:
Gen 0: 24414
Gen 1: 0
Gen 2: 0

.NET Core 3.0:
Gen 0: 352107
Gen 1: 1
Gen 2: 0

@ghost
Copy link

ghost commented May 23, 2019

@smoogipoo Thanks, I got access to a mac and can easily reproduce this with just object.

@sergiy-k sergiy-k assigned ghost May 23, 2019
ghost referenced this issue in dotnet/coreclr Jun 5, 2019
* Fix PAL_GetLogicalProcessorCacheSizeFromOS on mac

In a previous PR
(ed52a00#diff-8447e54277bb962d167a77bb260760d7R1879),
GetCacheSizePerLogicalCpu was changed to no longer rely on cpuid on
amd64 systems; instead it uses GetLogicalProcessorCacheSizeFromOS().
Unfortunately that function consisted of a number of `#if`s, none of
which were active on macs, and we just returned 0. This caused us to
default to a gen0size of only 0.25MB, causing many GCs.

Fixed by adding a new case that uses `sysctlbyname`.

Fix #24658

* Fixes from code review

* Check for function sysctlbyname instead of header
@smoogipoo
Copy link
Author

Is the fix for this supposed to be in preview 6? These are the current stats for construction of object:

Runtime Mean Error StdDev Gen 0/1k Op Gen 1/1k Op Gen 2/1k Op Allocated Memory/Op
2.2.5 4.580 ns 0.0334 ns 0.0279 ns 0.0076 - - 24 B
3.0.0-preview5-27626-15 9.348 ns 0.1417 ns 0.1326 ns 0.1469 - - 24 B
3.0.0-preview6-27804-01 8.938 ns 0.1034 ns 0.0916 ns 0.1469 - - 24 B

@Maoni0
Copy link
Member

Maoni0 commented Jun 24, 2019

@Andy-MS

@sergiy-k
Copy link
Contributor

This is not in Preview 6. It was merged too late. It is included into Preview 7.

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 13, 2020
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants