-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9686049
commit ef1293a
Showing
7 changed files
with
371 additions
and
134 deletions.
There are no files selected for viewing
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
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
101 changes: 101 additions & 0 deletions
101
src/Agent/NewRelic/Agent/Core/Samplers/GCSamplerModernReflectionHelper.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Copyright 2020 New Relic, Inc. All rights reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using System; | ||
using System.Linq.Expressions; | ||
using System.Reflection; | ||
using NewRelic.Reflection; | ||
|
||
namespace NewRelic.Agent.Core.Samplers | ||
{ | ||
// to allow for unit testing | ||
public interface IGCSamplerModernReflectionHelper | ||
{ | ||
Func<object, object> GetGenerationInfo { get; } | ||
bool ReflectionFailed { get; } | ||
Func<object, object> GCGetMemoryInfo_Invoker { get; } | ||
Func<object, object> GCGetTotalAllocatedBytes_Invoker { get; } | ||
|
||
bool HasGCOccurred {get;} | ||
} | ||
|
||
public class GCSamplerModernReflectionHelper : IGCSamplerModernReflectionHelper | ||
{ | ||
public Func<object, object> GetGenerationInfo { get; private set; } | ||
public bool ReflectionFailed { get; private set; } | ||
public Func<object, object> GCGetMemoryInfo_Invoker { get; private set; } | ||
public Func<object, object> GCGetTotalAllocatedBytes_Invoker { get; private set; } | ||
|
||
public GCSamplerModernReflectionHelper() | ||
{ | ||
var assembly = Assembly.Load("System.Runtime"); | ||
var gcType = assembly.GetType("System.GC"); | ||
var paramType = assembly.GetType("System.GCKind"); | ||
var returnType = assembly.GetType("System.GCMemoryInfo"); | ||
|
||
if (!VisibilityBypasser.Instance.TryGenerateOneParameterStaticMethodCaller(gcType, "GetGCMemoryInfo", paramType, returnType, out var accessor)) | ||
{ | ||
ReflectionFailed = true; | ||
} | ||
else | ||
GCGetMemoryInfo_Invoker = accessor; | ||
|
||
if (!ReflectionFailed) | ||
{ | ||
paramType = assembly.GetType("System.Boolean"); | ||
returnType = assembly.GetType("System.Int64"); | ||
if (!VisibilityBypasser.Instance.TryGenerateOneParameterStaticMethodCaller(gcType, "GetTotalAllocatedBytes", paramType, returnType, out var accessor1)) | ||
{ | ||
ReflectionFailed = true; | ||
} | ||
else | ||
GCGetTotalAllocatedBytes_Invoker = accessor1; | ||
} | ||
|
||
if (!ReflectionFailed) | ||
GetGenerationInfo = GCMemoryInfoHelper.GenerateGetMemoryInfoMethod(); | ||
} | ||
|
||
public bool HasGCOccurred => GC.CollectionCount(0) > 0; | ||
} | ||
|
||
internal static class GCMemoryInfoHelper | ||
{ | ||
/// <summary> | ||
/// Generate a function that takes a GCMemoryInfo instance as an input parameter and | ||
/// returns an array of GCGenerationInfo instances. | ||
/// </summary> | ||
public static Func<object, object> GenerateGetMemoryInfoMethod() | ||
{ | ||
var assembly = Assembly.Load("System.Runtime"); | ||
var gcMemoryInfoType = assembly.GetType("System.GCMemoryInfo"); | ||
|
||
// Define a parameter expression for the input object | ||
var inputParameter = Expression.Parameter(typeof(object), "input"); | ||
|
||
// Cast the input parameter to GCMemoryInfo | ||
var gcMemoryInfoParameter = Expression.Convert(inputParameter, gcMemoryInfoType); | ||
|
||
// Get the GenerationInfo property | ||
var generationInfoProperty = gcMemoryInfoType.GetProperty("GenerationInfo"); | ||
|
||
// Access the GenerationInfo property | ||
var accessGenerationInfo = Expression.Property(gcMemoryInfoParameter, generationInfoProperty); | ||
|
||
// Get the ReadOnlySpan<GCGenerationInfo> type using the full type name | ||
var readOnlySpanType = assembly.GetType("System.ReadOnlySpan`1[[System.GCGenerationInfo, System.Private.CoreLib]]"); | ||
|
||
// Get the ToArray method of ReadOnlySpan<GCGenerationInfo> | ||
var toArrayMethod = readOnlySpanType.GetMethod("ToArray", BindingFlags.Public | BindingFlags.Instance); | ||
|
||
// Call ToArray() on GenerationInfo | ||
var callToArray = Expression.Call(accessGenerationInfo, toArrayMethod); | ||
|
||
// Create a lambda expression | ||
var lambda = Expression.Lambda<Func<object, object>>(Expression.Convert(callToArray, typeof(object)), inputParameter); | ||
|
||
// Compile the lambda expression into a delegate | ||
return lambda.Compile(); | ||
} | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
src/Agent/NewRelic/Agent/Core/Samplers/ImmutableGCSample.cs
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright 2020 New Relic, Inc. All rights reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
using System; | ||
|
||
namespace NewRelic.Agent.Core.Samplers | ||
{ | ||
public class ImmutableGCSample | ||
{ | ||
public readonly DateTime LastSampleTime; | ||
public readonly DateTime CurrentSampleTime; | ||
|
||
public readonly long TotalMemoryBytes; // In-use memory on the GC heap as of current GC | ||
public readonly long TotalAllocatedBytes; // total memory allocated on GC heap since process start | ||
public readonly long TotalCommittedBytes;// committed virtual memory as of current GC | ||
|
||
public readonly long[] GCHeapSizesBytes; // heap sizes as of current GC | ||
public readonly int[] GCCollectionCounts; // number of collections since last sample | ||
public readonly long[] GCFragmentationSizesBytes; // heap fragmentation as of current GC | ||
|
||
public ImmutableGCSample() | ||
{ | ||
LastSampleTime = CurrentSampleTime = DateTime.MinValue; | ||
GCHeapSizesBytes = new long[5]; | ||
GCCollectionCounts = new int[5]; | ||
GCFragmentationSizesBytes = new long[5]; | ||
} | ||
|
||
public ImmutableGCSample(DateTime lastSampleTime, DateTime currentSampleTime, long totalMemoryBytes, long totalAllocatedBytes, long totalCommittedBytes, long[] heapSizesBytes, int[] rawCollectionCounts, long[] fragmentationSizesBytes) | ||
{ | ||
LastSampleTime = lastSampleTime; | ||
CurrentSampleTime = currentSampleTime; | ||
|
||
TotalMemoryBytes = totalMemoryBytes; | ||
|
||
TotalAllocatedBytes = totalAllocatedBytes; | ||
TotalCommittedBytes = totalCommittedBytes; | ||
|
||
GCHeapSizesBytes = heapSizesBytes; | ||
GCFragmentationSizesBytes = fragmentationSizesBytes; | ||
|
||
// TODO: verify length is 5 as expected | ||
GCCollectionCounts = new int[rawCollectionCounts.Length]; | ||
// Gen 1 | ||
GCCollectionCounts[0] = rawCollectionCounts[0] - rawCollectionCounts[1]; | ||
// Gen 2 | ||
GCCollectionCounts[1] = rawCollectionCounts[1] - rawCollectionCounts[2]; | ||
// Gen 3 | ||
GCCollectionCounts[2] = rawCollectionCounts[2]; | ||
|
||
// LOH | ||
GCCollectionCounts[3] = rawCollectionCounts[3]; // or does this need to be [3] - [4]?? | ||
// POH | ||
GCCollectionCounts[4] = rawCollectionCounts[4]; //?? | ||
} | ||
} | ||
} |
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
Oops, something went wrong.