Skip to content

Instantly share code, notes, and snippets.

@noahfalk
Created May 19, 2020 05:22
Show Gist options
  • Save noahfalk/82cc9fc6c1a2ae0ac2e189bb317a6c7e to your computer and use it in GitHub Desktop.
Save noahfalk/82cc9fc6c1a2ae0ac2e189bb317a6c7e to your computer and use it in GitHub Desktop.
Sampling the new GC API to get periodic reports of fragmentation
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