Created
May 19, 2020 05:22
-
-
Save noahfalk/82cc9fc6c1a2ae0ac2e189bb317a6c7e to your computer and use it in GitHub Desktop.
Sampling the new GC API to get periodic reports of fragmentation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace SampleApp | |
{ | |
class Program | |
{ | |
static List<object> s_objects = new List<object>(); | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Note: This sample always computes 0% because the mocked API doesn't have any data in it. Using a real implementation would resolve that"); | |
Timer t = new Timer(OnTimer, null, 0, 1000); | |
Task.Run(AllocateMemory); | |
Console.ReadLine(); | |
} | |
static void AllocateMemory() | |
{ | |
while (true) | |
{ | |
s_objects.Add(new byte[50_000]); | |
Thread.Sleep(10); | |
} | |
} | |
static void OnTimer(object? state) | |
{ | |
GCMemoryInfo memInfo = GC.GetGCInfo(); | |
// add up the GC bytes and fragmentation GC bytes in each generation to get the total for the whole GC | |
long totalGCBytes = 0; | |
long totalFragmentationBytes = 0; | |
foreach(GCGenerationInfo gen in memInfo.GenerationInfo) | |
{ | |
totalGCBytes += gen.SizeBytes; | |
totalFragmentationBytes += totalFragmentationBytes; | |
} | |
double fragPercentage = totalGCBytes == 0 ? 0 : totalFragmentationBytes * 100.0 / totalGCBytes; | |
Console.WriteLine($"Last GC fragmentation is {fragPercentage:g2}%"); | |
} | |
} | |
#region A non-functional mockup of the in-progress proposed runtime API | |
public readonly ref struct GCMemoryInfo | |
{ | |
// Existing properties | |
public long HighMemoryLoadThresholdBytes { get; } | |
public long MemoryLoadBytes { get; } | |
public long TotalAvailableMemoryBytes { get; } | |
public long HeapSizeBytes { get; } | |
public long FragmentedBytes { get; } | |
// New properties | |
public long Index { get; } | |
public int Generation { get; } | |
public bool Compacted { get; } | |
public bool Concurrent { get; } | |
public long CommittedBytes { get; } | |
public long PromotedBytes { get; } | |
public long PinnedHandlesCount { get; } | |
public long FinalizationPendingCount { get; } | |
public ReadOnlySpan<TimeSpan> PauseDurations { get; } | |
public double PauseTimePercentage { get; } | |
public ReadOnlySpan<GCGenerationInfo> GenerationInfo { get; } | |
} | |
// New type | |
public readonly struct GCGenerationInfo | |
{ | |
public long SizeBytes { get; } | |
public long FragmentationBytes { get; } | |
} | |
class GC | |
{ | |
public static GCMemoryInfo GetGCInfo() | |
{ | |
return new GCMemoryInfo(); | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment