Fix EventPipe EventHandle Caching for TraceLogging (dotnet/coreclr#18355)
authorBrian Robbins <brianrob@microsoft.com>
Sat, 9 Jun 2018 00:44:11 +0000 (17:44 -0700)
committerGitHub <noreply@github.com>
Sat, 9 Jun 2018 00:44:11 +0000 (17:44 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/80f546fbd6161163a3383eb9574d653a768c3278

src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs

index f56a100..05b529e 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventPipeEventProvider.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventPipeMetadataGenerator.cs" />
     <Compile Condition="Exists('$(IntermediateOutputPath)..\eventing\DotNETRuntimeEventSource.cs')" Include="$(IntermediateOutputPath)..\eventing\DotNETRuntimeEventSource.cs" />
+    <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventHandleTable.cs" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Contracts\Contracts.cs" />
   </ItemGroup>
   <Import Project="ILLink.targets" />
   <Import Project="GenerateCompilerResponseFile.targets" />
-</Project>
+</Project>
\ No newline at end of file
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventHandleTable.cs
new file mode 100644 (file)
index 0000000..9afc1cf
--- /dev/null
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+
+namespace System.Diagnostics.Tracing
+{
+#if FEATURE_PERFTRACING
+    /// <summary>
+    /// Per-EventSource data structure for caching EventPipe EventHandles associated with TraceLogging events.
+    /// </summary>
+    internal sealed class TraceLoggingEventHandleTable
+    {
+        private const int DefaultLength = 10;
+        private IntPtr[] m_innerTable;
+
+        internal TraceLoggingEventHandleTable()
+        {
+            m_innerTable = new IntPtr[DefaultLength];
+        }
+
+        internal IntPtr this[int eventID]
+        {
+            get
+            {
+                IntPtr ret = IntPtr.Zero;
+                IntPtr[] innerTable = Volatile.Read(ref m_innerTable);
+
+                if (eventID >= 0 && eventID < innerTable.Length)
+                {
+                    ret = innerTable[eventID];
+                }
+
+                return ret;
+            }
+        }
+
+        internal void SetEventHandle(int eventID, IntPtr eventHandle)
+        {
+            // Set operations must be serialized to ensure that re-size operations don't lose concurrent writes.
+            Debug.Assert(Monitor.IsEntered(this));
+
+            if (eventID >= m_innerTable.Length)
+            {
+                int newSize = m_innerTable.Length * 2;
+                if (newSize <= eventID)
+                {
+                    newSize = eventID + 1;
+                }
+
+                IntPtr[] newTable = new IntPtr[newSize];
+                Array.Copy(m_innerTable, 0, newTable, 0, m_innerTable.Length);
+                Volatile.Write(ref m_innerTable, newTable);
+            }
+
+            m_innerTable[eventID] = eventHandle;
+        }
+    }
+#endif
+}
index b1c7327..a7daf5e 100644 (file)
@@ -42,10 +42,6 @@ namespace System.Diagnostics.Tracing
         internal readonly int identity;
         internal readonly byte[] nameMetadata;
 
-#if FEATURE_PERFTRACING
-        private readonly object eventHandleCreationLock = new object();
-#endif
-
         public NameInfo(string name, EventTags tags, int typeMetadataSize)
         {
             this.name = name;
@@ -82,14 +78,14 @@ namespace System.Diagnostics.Tracing
         }
 
 #if FEATURE_PERFTRACING
-        public IntPtr GetOrCreateEventHandle(EventProvider provider, ConcurrentDictionary<int, IntPtr> eventHandleMap, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
+        public IntPtr GetOrCreateEventHandle(EventProvider provider, TraceLoggingEventHandleTable eventHandleTable, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
         {
-            IntPtr eventHandle = IntPtr.Zero;
-            if(!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
+            IntPtr eventHandle;
+            if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
             {
-                lock (eventHandleCreationLock)
+                lock (eventHandleTable)
                 {
-                    if (!eventHandleMap.TryGetValue(descriptor.EventId, out eventHandle))
+                    if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
                     {
                         byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(
                             descriptor.EventId,
@@ -115,6 +111,9 @@ namespace System.Diagnostics.Tracing
                                     metadataLength);
                             }
                         }
+
+                        // Cache the event handle.
+                        eventHandleTable.SetEventHandle(descriptor.EventId, eventHandle);
                     }
                 }
             }
index 0bf6657..0553f98 100644 (file)
@@ -24,7 +24,6 @@ using System.Resources;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Collections.ObjectModel;
-using System.Collections.Concurrent;
 
 #if !ES_BUILD_AGAINST_DOTNET_V35
 using Contract = System.Diagnostics.Contracts.Contract;
@@ -49,7 +48,7 @@ namespace System.Diagnostics.Tracing
 #endif
 
 #if FEATURE_PERFTRACING
-        private ConcurrentDictionary<int, IntPtr> m_eventHandleMap = new ConcurrentDictionary<int, IntPtr>();
+        private readonly TraceLoggingEventHandleTable m_eventHandleTable = new TraceLoggingEventHandleTable();
 #endif
 
         /// <summary>
@@ -437,7 +436,7 @@ namespace System.Diagnostics.Tracing
             EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
 
 #if FEATURE_PERFTRACING
-            IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleMap, descriptor, eventTypes);
+            IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
             Debug.Assert(eventHandle != IntPtr.Zero);
 #else
             IntPtr eventHandle = IntPtr.Zero;
@@ -552,7 +551,7 @@ namespace System.Diagnostics.Tracing
                 }
 
 #if FEATURE_PERFTRACING
-                    IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleMap, descriptor, eventTypes);
+                    IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
                     Debug.Assert(eventHandle != IntPtr.Zero);
 #else
                     IntPtr eventHandle = IntPtr.Zero;
@@ -621,7 +620,7 @@ namespace System.Diagnostics.Tracing
                     }
 
 #if FEATURE_PERFTRACING
-                    IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleMap, descriptor, eventTypes);
+                    IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
                     Debug.Assert(eventHandle != IntPtr.Zero);
 #else
                     IntPtr eventHandle = IntPtr.Zero;