Skip to content

experiment: gcdump reading #4265

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<PropertyGroup>
<!--Generate xml docs for all projects under 'src'-->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- <GenerateDocumentationFile>true</GenerateDocumentationFile>-->

<Authors>Sentry Team and Contributors</Authors>
<Company>Sentry.io</Company>
Expand Down
60 changes: 30 additions & 30 deletions src/Sentry.Profiling/Downsampler.cs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
/// <summary>
/// Reduce sampling rate from 1 Hz that is the default for the provider to the configured SamplingRateMs.
/// </summary>
internal class Downsampler
{
private static double _samplingRateMs = (double)1_000 / 101; // 101 Hz

// Maps from ThreadIndex to the last sample timestamp for that thread.
private GrowableArray<double> _prevThreadSamples = new(10);

public void NewThreadAdded(int threadIndex)
{
if (threadIndex >= _prevThreadSamples.Count)
{
_prevThreadSamples.Count = threadIndex + 1;
_prevThreadSamples[threadIndex] = double.MinValue;
}
}

public bool ShouldSample(int threadIndex, double timestampMs)
{
Debug.Assert(threadIndex < _prevThreadSamples.Count, "ThreadIndex too large - you must call NewThreadAdded() if a new thread is added.");
if (_prevThreadSamples[threadIndex] + _samplingRateMs <= timestampMs)
{
_prevThreadSamples[threadIndex] = timestampMs;
return true;
}
return false;
}
}
// /// <summary>
// /// Reduce sampling rate from 1 Hz that is the default for the provider to the configured SamplingRateMs.
// /// </summary>
// internal class Downsampler
// {
// private static double _samplingRateMs = (double)1_000 / 101; // 101 Hz
//
// // Maps from ThreadIndex to the last sample timestamp for that thread.
// private GrowableArray<double> _prevThreadSamples = new(10);
//
// public void NewThreadAdded(int threadIndex)
// {
// if (threadIndex >= _prevThreadSamples.Count)
// {
// _prevThreadSamples.Count = threadIndex + 1;
// _prevThreadSamples[threadIndex] = double.MinValue;
// }
// }
//
// public bool ShouldSample(int threadIndex, double timestampMs)
// {
// Debug.Assert(threadIndex < _prevThreadSamples.Count, "ThreadIndex too large - you must call NewThreadAdded() if a new thread is added.");
// if (_prevThreadSamples[threadIndex] + _samplingRateMs <= timestampMs)
// {
// _prevThreadSamples[threadIndex] = timestampMs;
// return true;
// }
// return false;
// }
// }
12 changes: 6 additions & 6 deletions src/Sentry.Profiling/SampleProfileBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal class SampleProfileBuilder
private readonly Dictionary<int, int> _threadIndexes = new();

// TODO make downsampling conditional once this is available: https://github.com/dotnet/runtime/issues/82939
private readonly Downsampler _downsampler = new();
// private readonly Downsampler _downsampler = new();

public SampleProfileBuilder(SentryOptions options, TraceLog traceLog)
{
Expand Down Expand Up @@ -61,10 +61,10 @@ internal void AddSample(TraceEvent data, double timestampMs)
return;
}

if (!_downsampler.ShouldSample(threadIndex, timestampMs))
{
return;
}
// if (!_downsampler.ShouldSample(threadIndex, timestampMs))
// {
// return;
// }

var stackIndex = AddStackTrace(callStackIndex);
if (stackIndex < 0)
Expand Down Expand Up @@ -204,7 +204,7 @@ private int AddThread(TraceThread thread)
});
value = Profile.Threads.Count - 1;
_threadIndexes[key] = value;
_downsampler.NewThreadAdded(_threadIndexes[key]);
// _downsampler.NewThreadAdded(_threadIndexes[key]);
}

return value;
Expand Down
4 changes: 2 additions & 2 deletions src/Sentry.Profiling/Sentry.Profiling.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
<None Include="$(MSBuildThisFileDirectory)buildTransitive\Sentry.Profiling.targets" Pack="true" PackagePath="build\Sentry.Profiling.targets" />
</ItemGroup>
<ItemGroup>
<ProfilingDependency Include="..\..\modules\perfview\src\FastSerialization\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.FastSerialization.dll" />
<!-- <ProfilingDependency Include="..\..\modules\perfview\src\FastSerialization\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.FastSerialization.dll" />-->
<ProfilingDependency Include="..\..\modules\perfview\src\TraceEvent\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.Tracing.TraceEvent.dll" />
<ProfilingDependency Include="..\..\modules\perfview\src\FastSerialization\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.FastSerialization.pdb" />
<!-- <ProfilingDependency Include="..\..\modules\perfview\src\FastSerialization\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.FastSerialization.pdb" />-->
<ProfilingDependency Include="..\..\modules\perfview\src\TraceEvent\bin\$(Configuration)\netstandard2.0\Microsoft.Diagnostics.Tracing.TraceEvent.pdb" />
</ItemGroup>
<ItemGroup>
Expand Down
4 changes: 0 additions & 4 deletions src/Sentry/ISpanData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ public static void SetMeasurement(this ISpanData spanData, string name, long val
spanData.SetMeasurement(name, new Measurement(value, unit));

/// <inheritdoc cref="SetMeasurement(Sentry.ISpanData,string,int,Sentry.MeasurementUnit)" />
#if !__MOBILE__
// ulong parameter is not CLS compliant
[CLSCompliant(false)]
#endif
public static void SetMeasurement(this ISpanData spanData, string name, ulong value,
MeasurementUnit unit = default) =>
spanData.SetMeasurement(name, new Measurement(value, unit));
Expand Down
38 changes: 36 additions & 2 deletions src/Sentry/Sentry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<PropertyGroup>
<Description>Official SDK for Sentry - Open-source error tracking that helps developers monitor and fix crashes in real time.</Description>
<NoWarn Condition="'$(TargetFramework)' == 'netstandard2.0'">$(NoWarn);RS0017</NoWarn>
<CLSCompliant Condition="'$(TargetPlatformIdentifier)' == ''">true</CLSCompliant>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

Expand Down Expand Up @@ -50,7 +49,42 @@
</Compile>
<Compile Remove="..\..\modules\Ben.Demystifier\**\obj\**" />
</ItemGroup>

<ItemGroup Condition="!$(TargetFramework.StartsWith('netstandard')) and !$(TargetFramework.StartsWith('net4'))">
<Compile Include="..\..\modules\perfview\src\HeapDump\**\*.cs"
Link="perfview\HeapDump\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<Compile Include="..\..\modules\perfview\src\MemoryGraph\**\*.cs"
Link="perfview\MemoryGraph\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<Compile Include="..\..\modules\perfview\src\Utilities\XmlUtilities.cs"
Link="perfview\Utilities\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<Compile Include="..\..\modules\perfview\src\Utilities\EnvironmentUtilities.cs"
Link="perfview\Utilities\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<Compile Include="..\..\modules\perfview\src\Utilities\StringUtilities.cs"
Link="perfview\Utilities\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<!-- Will probably conflict with Sentry.Profiling -->
<Compile Include="..\..\modules\perfview\src\FastSerialization\**\*.cs"
Link="perfview\FastSerialization\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />
<Compile Include="..\..\modules\perfview\src\HeapDumpCommon\DotNetHeapInfo.cs"
Link="perfview\HeapDumpCommon\%(RecursiveDir)\%(Filename)%(Extension)"
Nullable="disable" />

<Compile Remove="..\..\modules\perfview\src\HeapDump\**\GCHeapDumper.cs" />
<Compile Remove="..\..\modules\perfview\src\HeapDump\**\Program.cs" />
<Compile Remove="..\..\modules\perfview\src\HeapDump\Properties\*.cs" />
<Compile Remove="..\..\modules\perfview\src\HeapDump\Utilities\*.cs" />
<Compile Remove="..\..\modules\perfview\**\obj\**" />
</ItemGroup>
<!-- <Compile Include="..\MemoryGraph\graph.cs">-->
<!-- <Link>MemoryGraph\graph.cs</Link>-->
<!-- </Compile>-->
<!-- <Compile Include="..\MemoryGraph\MemoryGraph.cs">-->
<!-- <Link>MemoryGraph\MemoryGraph.cs</Link>-->
<!-- </Compile>-->
<!-- Ben.Demystifier also needs System.Reflection.Metadata 5.0.0 or higher on all platforms. -->
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard')) or $(TargetFramework.StartsWith('net4'))">
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
Expand Down
3 changes: 0 additions & 3 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1199,9 +1199,6 @@ public bool JsonPreserveReferences
/// <remarks>
/// This is for Sentry use only, and can change without a major version bump.
/// </remarks>
#if !__MOBILE__
[CLSCompliant(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never)]
public Func<string, PEReader?>? AssemblyReader { get; set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,13 +445,13 @@ public void ProfilerIntegration_WithProfilingEnabled_SetsFactory()
[SkippableFact]
public void Downsampler_ShouldSample_Works()
{
var sut = new Downsampler();
sut.NewThreadAdded(0);
Assert.True(sut.ShouldSample(0, 5));
Assert.False(sut.ShouldSample(0, 3));
Assert.False(sut.ShouldSample(0, 6));
Assert.True(sut.ShouldSample(0, 15));
Assert.False(sut.ShouldSample(0, 6));
Assert.False(sut.ShouldSample(0, 16));
// var sut = new Downsampler();
// sut.NewThreadAdded(0);
// Assert.True(sut.ShouldSample(0, 5));
// Assert.False(sut.ShouldSample(0, 3));
// Assert.False(sut.ShouldSample(0, 6));
// Assert.True(sut.ShouldSample(0, 15));
// Assert.False(sut.ShouldSample(0, 6));
// Assert.False(sut.ShouldSample(0, 16));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[assembly: System.CLSCompliant(true)]
namespace Sentry
namespace Sentry
{
public enum AttachmentType
{
Expand Down Expand Up @@ -663,7 +662,6 @@ namespace Sentry
public class SentryOptions
{
public SentryOptions() { }
[System.CLSCompliant(false)]
public System.Func<string, System.Reflection.PortableExecutable.PEReader?>? AssemblyReader { get; set; }
public bool AttachStacktrace { get; set; }
public bool AutoSessionTracking { get; set; }
Expand Down Expand Up @@ -1060,7 +1058,6 @@ namespace Sentry
public static void SetMeasurement(this Sentry.ISpanData spanData, string name, double value, Sentry.MeasurementUnit unit = default) { }
public static void SetMeasurement(this Sentry.ISpanData spanData, string name, int value, Sentry.MeasurementUnit unit = default) { }
public static void SetMeasurement(this Sentry.ISpanData spanData, string name, long value, Sentry.MeasurementUnit unit = default) { }
[System.CLSCompliant(false)]
public static void SetMeasurement(this Sentry.ISpanData spanData, string name, ulong value, Sentry.MeasurementUnit unit = default) { }
}
public static class SpanExtensions
Expand Down
59 changes: 59 additions & 0 deletions test/Sentry.Tests/MemDumpTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#if NET8_0_OR_GREATER
using Graphs;
using Microsoft.Diagnostics.Utilities;

namespace Sentry.Tests;

public class MemDumpTests
{
// private readonly ITestOutputHelper _testOutputHelper;
// private readonly IDiagnosticLogger _testOutputLogger;

// public MemDumpTests(ITestOutputHelper output, ITestOutputHelper testOutputHelper)
// {
// _testOutputHelper = testOutputHelper;
// _testOutputLogger = new TestOutputDiagnosticLogger(output);
// }

[Fact]
public void MemDump_Tests()
{
var path = "/Users/bruno/git/ConsoleApp1/ConsoleApp1/ConsoleApp1/20250526_133030_1.gcdump";
var dump = new GCHeapDump(path);
var graph = dump.MemoryGraph;
Console.WriteLine(dump.CreationTool);
Console.WriteLine(dump.CollectionLog);
var ret = new Graph.SizeAndCount[(int)graph.NodeTypeIndexLimit];
for (int i = 0; i < ret.Length; i++)
{
ret[i] = new Graph.SizeAndCount((NodeTypeIndex)i);
}

var nodeStorage = graph.AllocNodeStorage();
for (NodeIndex idx = 0; idx < graph.NodeIndexLimit; idx++)
{
var node = graph.GetNode(idx, nodeStorage);
var sizeAndCount = ret[(int)node.TypeIndex];
sizeAndCount.Count++;
sizeAndCount.Size += node.Size;
}

Array.Sort(ret, (Graph.SizeAndCount x, Graph.SizeAndCount y) => y.Size.CompareTo(x.Size));
Console.WriteLine("<HistogramByType Size=\"{0}\" Count=\"{1}\">", dump.MemoryGraph.TotalSize, (int)dump.MemoryGraph.NodeIndexLimit);
var typeStorage = new NodeType(graph);
var sizeAndCounts = graph.GetHistogramByType();
long minSize = 0;
foreach (var sizeAndCount in sizeAndCounts)
{
if (sizeAndCount.Size <= minSize)
{
break;
}

var line = string.Format("Name=\"{0}\" Size=\"{1}\" Count=\"{2}\"",
graph.GetType(sizeAndCount.TypeIdx, typeStorage).Name, sizeAndCount.Size, sizeAndCount.Count);
Console.WriteLine(line);
}
}
}
#endif
Loading