From: Günther Foidl Date: Wed, 19 May 2021 15:57:58 +0000 (+0200) Subject: Enabled POH in dotnet-dump dumpgen command (#2260) X-Git-Tag: submit/tizen/20210909.063632~15^2~17 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b5e84b569e831dfa1f78c2f5acaf5e1349ea4af1;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Enabled POH in dotnet-dump dumpgen command (#2260) * Enabled POH in dotnet-dump dumpgen command * Tests * Exclude POH segments from Gen2 * Corrected pattern to match output for x64/x86 For x64 it's 10024, for x86 iit's 10012, so just check for 100. I don't want to check just for byte[], as there could be any other byte arrays too. * Fix dump file names not being unique. * When the same "TestName" is being used but with different debuggee arguments the resulting dump name ends up being the same and overwrites the existing one. This caused the uploaded dump to look different from the log. * Update CLRMD to patched version for POH analysis --- diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/ClrMDHelper.cs b/src/Microsoft.Diagnostics.ExtensionCommands/ClrMDHelper.cs index 193ff2f17..9bb491765 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/ClrMDHelper.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/ClrMDHelper.cs @@ -733,7 +733,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands } return start != end; case GCGeneration.Generation2: - if (!segment.IsLargeObjectSegment) + if (!(segment.IsLargeObjectSegment || segment.IsPinnedObjectSegment)) { start = segment.Generation2.Start; end = segment.Generation2.End; @@ -746,6 +746,13 @@ namespace Microsoft.Diagnostics.ExtensionCommands end = segment.End; } return start != end; + case GCGeneration.PinnedObjectHeap: + if (segment.IsPinnedObjectSegment) + { + start = segment.Start; + end = segment.End; + } + return start != end; default: return false; } diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/DumpGen.cs b/src/Microsoft.Diagnostics.ExtensionCommands/DumpGen.cs index cb27b18cf..9261b1c3a 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/DumpGen.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/DumpGen.cs @@ -2,14 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Diagnostics.Runtime; +using System; using System.Collections.Generic; using System.Linq; -using System; +using Microsoft.Diagnostics.Runtime; namespace Microsoft.Diagnostics.ExtensionCommands { - public class DumpGen { private readonly ClrMDHelper _helper; @@ -48,12 +47,9 @@ namespace Microsoft.Diagnostics.ExtensionCommands .Where(obj => obj.Type.MethodTable == methodTableAddress); } - private static bool IsTypeNameMatching(string typeName, string typeNameFilter) { - return typeName.ToLower().Contains(typeNameFilter.ToLower()); + return typeName.IndexOf(typeNameFilter, StringComparison.OrdinalIgnoreCase) >= 0; } - } - } diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/DumpGenCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/DumpGenCommand.cs index fbd561d5d..da86dcbd4 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/DumpGenCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/DumpGenCommand.cs @@ -107,8 +107,10 @@ namespace Microsoft.Diagnostics.ExtensionCommands return GCGeneration.Generation2; case "loh": return GCGeneration.LargeObjectHeap; + case "poh": + return GCGeneration.PinnedObjectHeap; default: - WriteLine($"{generation} is not a supported generation (gen0, gen1, gen2, loh)"); + WriteLine($"{generation} is not a supported generation (gen0, gen1, gen2, loh, poh)"); return GCGeneration.NotSet; } } @@ -131,6 +133,7 @@ Generation number can take the following values (case insensitive): - gen1 - gen2 - loh +- poh > dumpgen gen0 Statistics: diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/GCGeneration.cs b/src/Microsoft.Diagnostics.ExtensionCommands/GCGeneration.cs index f26523181..d293a3312 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/GCGeneration.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/GCGeneration.cs @@ -10,6 +10,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands Generation0 = 1, Generation1 = 2, Generation2 = 3, - LargeObjectHeap = 4 + LargeObjectHeap = 4, + PinnedObjectHeap = 5 } } diff --git a/src/SOS/SOS.UnitTests/Debuggees/DotnetDumpCommands/Program.cs b/src/SOS/SOS.UnitTests/Debuggees/DotnetDumpCommands/Program.cs index 120cddffe..6afe5e7f8 100644 --- a/src/SOS/SOS.UnitTests/Debuggees/DotnetDumpCommands/Program.cs +++ b/src/SOS/SOS.UnitTests/Debuggees/DotnetDumpCommands/Program.cs @@ -127,6 +127,11 @@ namespace DotnetDumpCommands // This object should go into LOH yield return new DumpSampleClass[50000]; +#if NET5_0_OR_GREATER + // This object should go into POH + yield return GC.AllocateUninitializedArray(10000, pinned: true); +#endif + for (var i = 0; i < 5; i++) { yield return new DumpSampleClass(); @@ -152,7 +157,6 @@ namespace DotnetDumpCommands public DateTime Date { get; set; } } - public struct DumpSampleStruct { public int IntValue; diff --git a/src/SOS/SOS.UnitTests/SOS.cs b/src/SOS/SOS.UnitTests/SOS.cs index 20a80e334..133eadc51 100644 --- a/src/SOS/SOS.UnitTests/SOS.cs +++ b/src/SOS/SOS.UnitTests/SOS.cs @@ -138,7 +138,6 @@ public class SOS { throw new SkipTestException("This test validates POH behavior, which was introduced in .net 5"); } - await RunTest(config, "GCPOH", "GCPOH.script", testName: "SOS.GCPOHTests", testDump: false); } @@ -214,6 +213,7 @@ public class SOS TestName = "SOS.StackAndOtherTests", DebuggeeName = "SymbolTestApp", DebuggeeArguments = "%DEBUG_ROOT%", + DumpNameSuffix = currentConfig.DebugType }); // This tests using regular Windows PDBs with no managed hosting. SOS should fallback @@ -228,6 +228,7 @@ public class SOS TestName = "SOS.StackAndOtherTests", DebuggeeName = "SymbolTestApp", DebuggeeArguments = "%DEBUG_ROOT%", + DumpNameSuffix = currentConfig.DebugType }); } } @@ -271,7 +272,7 @@ public class SOS DebuggeeArguments = desktopTestParameters, UsePipeSync = true, DumpGenerator = SOSRunner.DumpGenerator.DotNetDump - }); ; + }); } [SkippableTheory, MemberData(nameof(GetConfigurations), "TestName", "DotnetDumpCommands")] @@ -282,9 +283,10 @@ public class SOS TestConfiguration = config, DebuggeeName = "DotnetDumpCommands", DebuggeeArguments = "dcd", + DumpNameSuffix = "dcd", UsePipeSync = true, DumpGenerator = SOSRunner.DumpGenerator.DotNetDump, - }); ; + }); } [SkippableTheory, MemberData(nameof(GetConfigurations), "TestName", "DotnetDumpCommands")] @@ -295,9 +297,10 @@ public class SOS TestConfiguration = config, DebuggeeName = "DotnetDumpCommands", DebuggeeArguments = "dumpgen", + DumpNameSuffix = "dumpgen", UsePipeSync = true, DumpGenerator = SOSRunner.DumpGenerator.DotNetDump, - }); ; + }); } [SkippableTheory, MemberData(nameof(Configurations))] diff --git a/src/SOS/SOS.UnitTests/SOSRunner.cs b/src/SOS/SOS.UnitTests/SOSRunner.cs index 53a08befd..4ba404e19 100644 --- a/src/SOS/SOS.UnitTests/SOSRunner.cs +++ b/src/SOS/SOS.UnitTests/SOSRunner.cs @@ -90,6 +90,8 @@ public class SOSRunner : IDisposable public bool DumpDiagnostics { get; set; } = true; + public string DumpNameSuffix { get; set; } + public bool IsValid() { return TestConfiguration != null && OutputHelper != null && DebuggeeName != null; @@ -973,7 +975,17 @@ public class SOSRunner : IDisposable TestConfiguration config = information.TestConfiguration; string dumpRoot = action == DebuggerAction.GenerateDump ? config.DebuggeeDumpOutputRootDir() : config.DebuggeeDumpInputRootDir(); if (!string.IsNullOrEmpty(dumpRoot)) { - return Path.Combine(dumpRoot, information.TestName + "." + information.DumpType.ToString() + ".dmp"); + var sb = new StringBuilder(); + sb.Append(information.TestName); + sb.Append("."); + sb.Append(information.DumpType.ToString()); + if (information.DumpNameSuffix != null) + { + sb.Append("."); + sb.Append(information.DumpNameSuffix); + } + sb.Append(".dmp"); + return Path.Combine(dumpRoot, sb.ToString()); } return null; } diff --git a/src/SOS/SOS.UnitTests/Scripts/DumpGen.script b/src/SOS/SOS.UnitTests/Scripts/DumpGen.script index 0c8617705..1f8e489cb 100644 --- a/src/SOS/SOS.UnitTests/Scripts/DumpGen.script +++ b/src/SOS/SOS.UnitTests/Scripts/DumpGen.script @@ -22,7 +22,7 @@ VERIFY: Hexadecimal address expected for -mt option COMMAND: dumpgen gen0 VERIFY: ^\s+MT\s+Count\s+TotalSize\s+Class Name -VERIFY:^\s+10\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass +VERIFY: ^\s+10\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass COMMAND: dumpgen gen0 -type DotnetDumpCommands VERIFY: ^\s+10\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass @@ -44,10 +44,16 @@ VERIFY: ^\s+3\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass COMMAND: dumpgen gen2 VERIFY: ^\s+5\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass +!VERIFY: ^\s+1\s+100\s+System.Byte\[\] COMMAND: dumpgen loh VERIFY: ^\s+1\s+\s+DotnetDumpCommands\.Program\+DumpSampleClass\[\] +IFDEF:MAJOR_RUNTIME_VERSION_GE_5 +COMMAND: dumpgen poh +VERIFY: ^\s+1\s+100\s+System.Byte\[\] +ENDIF:MAJOR_RUNTIME_VERSION_GE_5 + SOSCOMMAND: dumpheap -stat ENDIF:NETCORE_OR_DOTNETDUMP