Skip to content

Commit 2c15afe

Browse files
committed
[DotnetTrace] Update profiles
1 parent a41a04a commit 2c15afe

File tree

3 files changed

+89
-7
lines changed

3 files changed

+89
-7
lines changed

src/Tools/dotnet-trace/CommandLine/Commands/CollectCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ private static async Task<int> Collect(CancellationToken ct, CommandLineConfigur
110110

111111
if (profile.Length == 0 && providers.Length == 0 && clrevents.Length == 0)
112112
{
113-
ConsoleWriteLine("No profile or providers specified, defaulting to trace profile 'cpu-sampling'");
114-
profile = "cpu-sampling";
113+
ConsoleWriteLine("No profile or providers specified, defaulting to trace profile 'dotnet-common'");
114+
profile = "dotnet-common";
115115
}
116116

117117
Dictionary<string, string> enabledBy = new();

src/Tools/dotnet-trace/CommandLine/Commands/CollectLinuxCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ private static List<string> BuildRecordTraceArgs(CollectLinuxArgs args)
174174
if (args.Profiles.Length == 0 && args.Providers.Length == 0 && string.IsNullOrEmpty(args.ClrEvents))
175175
{
176176
Console.WriteLine("No profile or providers specified, defaulting to trace profile 'dotnet-common'");
177-
profiles = new[] { "cpu-sampling" };
177+
profiles = new[] { "dotnet-common" };
178178
}
179179
List<EventPipeProvider> providerCollection = ProviderUtils.ToProviders(args.Providers, args.ClrEvents, args.ClrEventLevel, profiles);
180180
foreach (EventPipeProvider provider in providerCollection)

src/Tools/dotnet-trace/CommandLine/Commands/ListProfilesCommandHandler.cs

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,52 @@ namespace Microsoft.Diagnostics.Tools.Trace
1414
{
1515
internal sealed class ListProfilesCommandHandler
1616
{
17+
private static long defaultKeyword = 0x1 | // GC
18+
0x4 | // Loader
19+
0x8 | // AssemblyLoader
20+
0x10 | // JIT
21+
0x8000 | // Exceptions
22+
0x10000 | // Threading
23+
0x20000 | // JittedMethodILToNativeMap
24+
0x1000000000; // Contention
25+
26+
private static string dotnetCommonDescription = """
27+
Lightweight .NET runtime diagnostics designed to stay low overhead.
28+
Includes:
29+
GC
30+
AssemblyLoader
31+
Jit
32+
Exception
33+
Threading
34+
JittedMethodILToNativeMap
35+
Compilation
36+
Contention
37+
Equivalent to --providers "Microsoft-Windows-DotNETRuntime:0x100003801D:4".
38+
""";
39+
1740
public static int GetProfiles()
1841
{
1942
try
2043
{
44+
Console.Out.WriteLine("dotnet-trace collect profiles:");
45+
int profileNameWidth = ProfileNamesMaxWidth(DotNETRuntimeProfiles);
2146
foreach (Profile profile in DotNETRuntimeProfiles)
2247
{
23-
Console.Out.WriteLine($"\t{profile.Name,-16} - {profile.Description}");
48+
PrintProfile(profile, profileNameWidth);
49+
}
50+
51+
if (OperatingSystem.IsLinux())
52+
{
53+
Console.Out.WriteLine("\ndotnet-trace collect-linux profiles:");
54+
profileNameWidth = Math.Max(profileNameWidth, ProfileNamesMaxWidth(LinuxPerfEventProfiles));
55+
foreach (Profile profile in DotNETRuntimeProfiles)
56+
{
57+
PrintProfile(profile, profileNameWidth);
58+
}
59+
foreach (Profile profile in LinuxPerfEventProfiles)
60+
{
61+
PrintProfile(profile, profileNameWidth);
62+
}
2463
}
2564

2665
return 0;
@@ -44,12 +83,17 @@ public static Command ListProfilesCommand()
4483

4584
internal static IEnumerable<Profile> DotNETRuntimeProfiles { get; } = new[] {
4685
new Profile(
47-
"cpu-sampling",
86+
"dotnet-common",
87+
new EventPipeProvider[] {
88+
new("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, defaultKeyword)
89+
},
90+
dotnetCommonDescription),
91+
new Profile(
92+
"dotnet-sampled-thread-time",
4893
new EventPipeProvider[] {
4994
new("Microsoft-DotNETCore-SampleProfiler", EventLevel.Informational),
50-
new("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, (long)ClrTraceEventParser.Keywords.Default)
5195
},
52-
"Useful for tracking CPU usage and general .NET runtime information. This is the default option if no profile or providers are specified."),
96+
"Samples .NET thread stacks (~100 Hz) to identify hotspots over time. Uses the runtime sample profiler with managed stacks."),
5397
new Profile(
5498
"gc-verbose",
5599
new EventPipeProvider[] {
@@ -104,6 +148,44 @@ public static Command ListProfilesCommand()
104148
"Captures ADO.NET and Entity Framework database commands")
105149
};
106150

151+
internal static IEnumerable<Profile> LinuxPerfEventProfiles { get; } = new[] {
152+
new Profile(
153+
"kernel-cpu",
154+
providers: Array.Empty<EventPipeProvider>(),
155+
description: "Kernel CPU sampling (perf-based), emitted as Universal.Events/cpu, for precise on-CPU attribution."),
156+
new Profile(
157+
"kernel-cswitch",
158+
providers: Array.Empty<EventPipeProvider>(),
159+
description: "Kernel thread context switches, emitted as Universal.Events/cswitch, for on/off-CPU and scheduler analysis.")
160+
};
161+
162+
private static int ProfileNamesMaxWidth(IEnumerable<Profile> profiles)
163+
{
164+
int maxWidth = 0;
165+
foreach (Profile profile in profiles)
166+
{
167+
if (profile.Name.Length > maxWidth)
168+
{
169+
maxWidth = profile.Name.Length;
170+
}
171+
}
172+
173+
return maxWidth;
174+
}
175+
176+
private static void PrintProfile(Profile profile, int nameColumnWidth)
177+
{
178+
string[] descriptionLines = profile.Description.Replace("\r\n", "\n").Split('\n');
179+
180+
Console.Out.WriteLine($"\t{profile.Name.PadRight(nameColumnWidth)} - {descriptionLines[0]}");
181+
182+
string continuationPrefix = $"\t{new string(' ', nameColumnWidth)} ";
183+
for (int i = 1; i < descriptionLines.Length; i++)
184+
{
185+
Console.Out.WriteLine(continuationPrefix + descriptionLines[i]);
186+
}
187+
}
188+
107189
/// <summary>
108190
/// Keywords for DiagnosticSourceEventSource provider
109191
/// </summary>

0 commit comments

Comments
 (0)