Skip to content

Commit

Permalink
Log FileVersions for In-Use .NET Runtimes During Collection (#1798)
Browse files Browse the repository at this point in the history
  • Loading branch information
brianrob authored Mar 30, 2023
1 parent ffceddb commit 6bf5398
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/PerfView/CommandLineArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ public bool ShouldZip
public DateTime EndTime;
public bool ForceNgenRundown;
public bool DumpHeap;
public bool DisableDotNetVersionLogging;

// Collect options
public bool NoGui;
Expand Down Expand Up @@ -561,6 +562,8 @@ private void SetupCommandLine(CommandLineParser parser)
"Displays the hexadecimal address rather than ? when the address is unknown.");
parser.DefineOptionalQualifier("ShowOptimizationTiers", ref ShowOptimizationTiers,
"Displays the optimization tier of each code version executed for the method.");
parser.DefineOptionalQualifier("DisableDotNetVersionLogging", ref DisableDotNetVersionLogging,
"Disables capturing of .NET version information during collection.");
parser.DefineOptionalQualifier("NoGui", ref NoGui,
"Use the Command line version of the command (like on ARM). Brings up a console window. For batch scripts/automation use /LogFile instead (see users guide under 'Scripting' for more).");
parser.DefineOptionalQualifier("SafeMode", ref SafeMode, "Turn off parallelism and other risky features.");
Expand Down
17 changes: 17 additions & 0 deletions src/PerfView/CommandProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ public void Run(CommandLineArgs parsedArgs)
Command cmd = null;
try
{
DotNetVersionLogger.Start();

Start(parsedArgs);
Thread.Sleep(100); // Allow time for the start rundown events OS events to happen.
DateTime startTime = DateTime.Now;
Expand Down Expand Up @@ -153,6 +155,7 @@ public void Run(CommandLineArgs parsedArgs)
}
finally
{
DotNetVersionLogger.Stop();
if (!success)
{
if (cmd != null)
Expand Down Expand Up @@ -205,6 +208,7 @@ public void Collect(CommandLineArgs parsedArgs)
}
else
{
DotNetVersionLogger.Start();
Start(parsedArgs);
WaitUntilCollectionDone(collectionCompleted, parsedArgs, DateTime.Now);
if (m_aborted)
Expand All @@ -218,6 +222,7 @@ public void Collect(CommandLineArgs parsedArgs)
}
finally
{
DotNetVersionLogger.Stop();
collectionCompleted.Set(); // This ensures that the GUI window closes.
if (!success)
{
Expand Down Expand Up @@ -2984,6 +2989,11 @@ public static string ParsedArgsAsString(string command, CommandLineArgs parsedAr
cmdLineArgs += " /ShowOptimizationTiers";
}

if (parsedArgs.DisableDotNetVersionLogging)
{
cmdLineArgs += " /DisableVersionLogging";
}

if (parsedArgs.ContinueOnError)
{
cmdLineArgs += " /ContinueOnError";
Expand Down Expand Up @@ -3445,6 +3455,12 @@ private void DoClrRundownForSession(string fileName, string sessionName, Command
try
{
Stopwatch sw = Stopwatch.StartNew();
if (!DotNetVersionLogger.Running)
{
DotNetVersionLogger.Start();
}

DotNetVersionLogger.StartRundown();
var rundownFile = Path.ChangeExtension(fileName, ".clrRundown.etl");
using (TraceEventSession clrRundownSession = new TraceEventSession(sessionName + "Rundown", rundownFile))
{
Expand Down Expand Up @@ -3582,6 +3598,7 @@ private void DoClrRundownForSession(string fileName, string sessionName, Command
WaitForRundownIdle(parsedArgs.MinRundownTime, parsedArgs.RundownTimeout, rundownFile);

// Complete perfview rundown.
DotNetVersionLogger.Stop();
PerfViewLogger.Log.CommandLineParameters(ParsedArgsAsString(null, parsedArgs), Environment.CurrentDirectory, AppInfo.VersionNumber);
PerfViewLogger.Log.StartAndStopTimes();
PerfViewLogger.Log.StopRundown();
Expand Down
156 changes: 156 additions & 0 deletions src/PerfView/DotNetVersionLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Clr;
using Microsoft.Diagnostics.Tracing.Session;

namespace PerfView
{
/// <summary>
/// Monitors for Runtime/Start events from the Microsoft-Windows-DotNETRuntime and Microsoft-Windows-DotNETRuntimeRundown providers
/// and logs the version information for the associated runtime DLLs.
/// </summary>
internal static class DotNetVersionLogger
{
private static VersionLogger _loggerInstance;

private sealed class VersionLogger : IDisposable
{
private const string SessionName = "PerfView-DotNetVersionLogger-Session";
private readonly static TextWriter Log = App.CommandProcessor.LogFile;
private TraceEventSession _session;
private AutoResetEvent _sessionStopEvent = new AutoResetEvent(false);
private HashSet<string> _loggedPaths = new HashSet<string>();

public void Dispose()
{
if (_session != null)
{
_session.Dispose();
_session = null;
}
}

public void Start()
{
try
{
_session = new TraceEventSession(SessionName);
_session.EnableProvider(
ClrTraceEventParser.ProviderGuid,
TraceEventLevel.Always,
(ulong)TraceEventKeyword.None,
new TraceEventProviderOptions() { EventIDsToEnable = new List<int> { 187 } });

_session.Source.Clr.RuntimeStart += OnRuntimeInformationStartEvent;
ClrRundownTraceEventParser rundownParser = new ClrRundownTraceEventParser(_session.Source);
rundownParser.RuntimeStart += OnRuntimeInformationStartEvent;

Task.Factory.StartNew(() =>
{
_session.Source.Process();
_sessionStopEvent.Set();
});
}
catch (Exception ex)
{
Log.WriteLine($"Failed to start dotnet version tracking: {ex}");
}
}

public void StartRundown()
{
try
{
_session.EnableProvider(
ClrRundownTraceEventParser.ProviderGuid,
TraceEventLevel.Always,
(ulong)TraceEventKeyword.None,
new TraceEventProviderOptions() { EventIDsToEnable = new List<int> { 187 } });
}
catch (Exception ex)
{
Log.WriteLine($"Failed to enable rundown provider: {ex}");
}
}

public void Stop()
{
if (_session != null)
{
_session.Dispose();
_session = null;

// Wait for the session to stop.
_sessionStopEvent.WaitOne();

try
{
foreach (string dllPath in _loggedPaths)
{
if (File.Exists(dllPath))
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(dllPath);
PerfViewLogger.Log.RuntimeVersion(dllPath, info.FileVersion);
}
}
}
catch (Exception ex)
{
Log.WriteLine($"Failed to enumerate .NET runtime version information: {ex}");
}
}
}

private void OnRuntimeInformationStartEvent(RuntimeInformationTraceData data)
{
_loggedPaths.Add(data.RuntimeDllPath);
}
}

public static bool Running
{
get { return _loggerInstance != null; }
}

public static void Start()
{
if (App.CommandLineArgs.DisableDotNetVersionLogging)
{
return;
}

Stop();

_loggerInstance = new VersionLogger();
_loggerInstance.Start();
}

public static void StartRundown()
{
if (_loggerInstance != null)
{
_loggerInstance.StartRundown();
}
}

public static void Stop()
{
if (App.CommandLineArgs.DisableDotNetVersionLogging)
{
return;
}

if (_loggerInstance != null)
{
_loggerInstance.Stop();
_loggerInstance.Dispose();
}
}
}
}
2 changes: 2 additions & 0 deletions src/PerfView/PerfViewLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public void EventStopTrigger(DateTime eventTime, int processID, int threadID, st
{ WriteEvent(25, eventTime, processID, threadID, processName, eventName, durationMSec); }
[Event(26)]
public void StopTriggerDebugMessage(DateTime eventTime, string message) { WriteEvent(26, eventTime, message); }
[Event(27)]
public void RuntimeVersion(string path, string version) { WriteEvent(27, path, version); }
public class Tasks
{
public const EventTask Tracing = (EventTask)1;
Expand Down
1 change: 1 addition & 0 deletions src/PerfViewCollect/PerfViewCollect.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Compile Include="..\PerfView\JitStats.cs" />
<Compile Include="..\PerfView\RuntimeLoaderStats.cs" />
<Compile Include="..\PerfView\FileVersionInformation.cs" />
<Compile Include="..\PerfView\DotNetVersionLogger.cs" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 6bf5398

Please sign in to comment.