<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
--- /dev/null
+// 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
+}
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;
}
#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,
metadataLength);
}
}
+
+ // Cache the event handle.
+ eventHandleTable.SetEventHandle(descriptor.EventId, eventHandle);
}
}
}
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;
#endif
#if FEATURE_PERFTRACING
- private ConcurrentDictionary<int, IntPtr> m_eventHandleMap = new ConcurrentDictionary<int, IntPtr>();
+ private readonly TraceLoggingEventHandleTable m_eventHandleTable = new TraceLoggingEventHandleTable();
#endif
/// <summary>
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;
}
#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;
}
#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;