From 8b18fc49e94e7a0109f9083ffc35bbeb5429eabc Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 17 Oct 2024 11:20:23 -0700 Subject: [PATCH 1/4] Add ETW events when ALCs are created or disposed --- src/Compilers/Core/Portable/CodeAnalysisEventSource.cs | 7 +++++++ .../DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs | 2 ++ .../Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj | 1 + 3 files changed, 10 insertions(+) diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs index 0808ff7ce5515..4cba778b74a7e 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -24,6 +24,7 @@ public static class Tasks public const EventTask SingleGeneratorRunTime = (EventTask)2; public const EventTask BuildStateTable = (EventTask)3; public const EventTask Compilation = (EventTask)4; + public const EventTask AnalyzerAssemblyLoader = (EventTask)5; } private CodeAnalysisEventSource() { } @@ -102,6 +103,12 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy [Event(8, Message = "Server compilation {0} completed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.Compilation)] internal void StopServerCompilation(string name) => WriteEvent(8, name); + [Event(9, Message = "ALC for directory '{0}' created", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Start, Task = Tasks.AnalyzerAssemblyLoader)] + internal void CreateAssemblyLoadContext(string directory) => WriteEvent(9, directory); + + [Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] + internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory); + private static unsafe EventData GetEventDataForString(string value, char* ptr) { fixed (char* ptr2 = value) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs index d3c5c1b354bd2..01591c5d6ff36 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs @@ -74,6 +74,7 @@ private partial Assembly Load(AssemblyName assemblyName, string assemblyOriginal { if (!_loadContextByDirectory.TryGetValue(fullDirectoryPath, out loadContext)) { + CodeAnalysisEventSource.Log.CreateAssemblyLoadContext(fullDirectoryPath); loadContext = new DirectoryLoadContext(fullDirectoryPath, this); _loadContextByDirectory[fullDirectoryPath] = loadContext; } @@ -110,6 +111,7 @@ private partial void DisposeWorker() { try { + CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory); context.Unload(); } catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical)) diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 31f3ea1946bc8..172991f821fa8 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -40,6 +40,7 @@ + From 3ef1c6b1f77a6e33bf9bbc4d2b77e1ee95b91914 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 17 Oct 2024 11:32:57 -0700 Subject: [PATCH 2/4] Address feedback --- src/Compilers/Core/Portable/CodeAnalysisEventSource.cs | 3 +++ .../Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs index 4cba778b74a7e..99165c33468c0 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -109,6 +109,9 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy [Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory); + [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] + internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(10, directory, errorMessage); + private static unsafe EventData GetEventDataForString(string value, char* ptr) { fixed (char* ptr2 = value) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs index 01591c5d6ff36..641d7dfe81fce 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerAssemblyLoader.Core.cs @@ -111,11 +111,12 @@ private partial void DisposeWorker() { try { - CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory); context.Unload(); + CodeAnalysisEventSource.Log.DisposeAssemblyLoadContext(context.Directory); } catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical)) { + CodeAnalysisEventSource.Log.DisposeAssemblyLoadContextException(context.Directory, ex.ToString()); } } From 53940a319a491a261fa2d50613eb5109ecb0ce4e Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 17 Oct 2024 11:34:08 -0700 Subject: [PATCH 3/4] fix --- src/Compilers/Core/Portable/CodeAnalysisEventSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs index 99165c33468c0..325be011e2b02 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -110,7 +110,7 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory); [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] - internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(10, directory, errorMessage); + internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(11, directory, errorMessage); private static unsafe EventData GetEventDataForString(string value, char* ptr) { From 08a2ec765abf311d17d5876dac045b1504a7af21 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 17 Oct 2024 11:40:45 -0700 Subject: [PATCH 4/4] use error level for exception case --- src/Compilers/Core/Portable/CodeAnalysisEventSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs index 325be011e2b02..7081fd195e492 100644 --- a/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs +++ b/src/Compilers/Core/Portable/CodeAnalysisEventSource.cs @@ -109,7 +109,7 @@ internal unsafe void NodeTransform(int nodeHashCode, string name, string tableTy [Event(10, Message = "ALC for directory '{0}' disposed", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] internal void DisposeAssemblyLoadContext(string directory) => WriteEvent(10, directory); - [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Informational, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] + [Event(11, Message = "ALC for directory '{0}' disposal failed with exception '{1}'", Keywords = Keywords.Performance, Level = EventLevel.Error, Opcode = EventOpcode.Stop, Task = Tasks.AnalyzerAssemblyLoader)] internal void DisposeAssemblyLoadContextException(string directory, string errorMessage) => WriteEvent(11, directory, errorMessage); private static unsafe EventData GetEventDataForString(string value, char* ptr)