// // Copyright (c) Microsoft Corporation. All rights reserved. // /*******************************************************************/ /* WARNING */ /* This file should be identical in the Bartok and Singularity */ /* depots. Master copy resides in Bartok Depot. Changes should be */ /* made to Bartok Depot and propagated to Singularity Depot. */ /*******************************************************************/ namespace System.GCs { using Microsoft.Bartok.Options; using System.Runtime.CompilerServices; using System.Threading; [NoCCtor] [MixinConditional("GCProfiling")] [Mixin(typeof(BaseCollector))] internal abstract class ProfilingBaseCollector : BaseCollector { #region Allocation [ManualRefCounts] internal override Object AllocateObject(VTable vtable, Thread currentThread) { Object result = base.AllocateObject(vtable, currentThread); if (GC.IsProfiling) { ProfileAllocation(result); } if (VTable.enableGCProfiling) { ulong size = (ulong) ObjectLayout.ObjectSize(vtable); RegisterNewObject(size); } return result; } [ManualRefCounts] internal override Array AllocateVector(VTable vtable, int numElements, Thread currentThread) { Array result = base.AllocateVector(vtable, numElements, currentThread); if (VTable.enableGCProfiling) { ulong size = (ulong) ObjectLayout.ArraySize(vtable, unchecked((uint) numElements)); RegisterNewObject(size); } return result; } [ManualRefCounts] internal override Array AllocateArray(VTable vtable, int rank, int totalElements, Thread currentThread) { Array result = base.AllocateArray(vtable, rank, totalElements, currentThread); if (VTable.enableGCProfiling) { ulong size = (ulong) ObjectLayout.ArraySize(vtable, unchecked((uint)totalElements)); RegisterNewObject(size); } return result; } [ManualRefCounts] internal override String AllocateString(int stringLength, Thread currentThread) { String result = base.AllocateString(stringLength, currentThread); if (VTable.enableGCProfiling) { ulong size = (ulong) ObjectLayout.StringSize(vtable, unchecked((uint)(stringLength+1))); RegisterNewObject(size); } return result; } #endregion #region Accounting internal override void RegisterHeapSize(ulong heapSize) { base.RegisterHeapSize(heapSize); if (minHeapSize < heapSize) { minHeapSize = heapSize; } lastLiveHeapSize = heapSize; bytesSinceGC = 0; } internal override void RegisterNewObject(ulong objectSize) { base.RegisterNewObject(objectSize); bytesAllocated += objectSize; objectsAllocated++; if (VTable.enableGCAccurateHeapSize) { bytesSinceGC += objectSize; if (lastLiveHeapSize + bytesSinceGC > minHeapSize) { GC.Collect(); } } } internal override void PrintAllocations() { if (VTable.enableGCProfiling) { #if !SINGULARITY Console.Error.WriteLine("Objects allocated: "+ objectsAllocated); Console.Error.WriteLine("Total bytes allocated (KB): "+ (bytesAllocated >> 10)); Console.Error.WriteLine("Min. heap size (KB): "+ (minHeapSize >> 10)); #endif } base.PrintAllocations(); } private static ulong lastLiveHeapSize; private static ulong minHeapSize; private static ulong bytesSinceGC; private static ulong bytesAllocated; private static ulong objectsAllocated; #endregion } }