Skip to content

Commit

Permalink
Add event to capture min/max threads (#70063)
Browse files Browse the repository at this point in the history
Event ThreadPoolMinMaxThreads added. 

Parameters are:
            ushort MinWorkerThreads
            ushort MaxWorkerThreads
            ushort MinIOCompletionThreads
            ushort MaxIOCompletionThreads
            ushort ClrInstanceID

It is fired in the ThreadPool constructor and in the SetMinThreads/SetMaxThreads functions.
  • Loading branch information
eduardo-vp authored Jun 17, 2022
1 parent 5df4473 commit 41d9c1c
Show file tree
Hide file tree
Showing 20 changed files with 319 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ internal sealed partial class NativeRuntimeEventSource : EventSource
[LibraryImport(RuntimeHelpers.QCall)]
internal static partial void LogThreadPoolWorkerThreadWait(uint ActiveWorkerThreadCount, uint RetiredWorkerThreadCount, ushort ClrInstanceID);

[NonEvent]
[LibraryImport(RuntimeHelpers.QCall)]
internal static partial void LogThreadPoolMinMaxThreads(ushort MinWorkerThreads, ushort MaxWorkerThreads, ushort MinIOCompletionThreads, ushort MaxIOCompletionThreads, ushort ClrInstanceID);

[NonEvent]
[LibraryImport(RuntimeHelpers.QCall)]
internal static partial void LogThreadPoolWorkerThreadAdjustmentSample(double Throughput, ushort ClrInstanceID);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/env/etmdummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#define FireEtwThreadPoolWorkerThreadAdjustmentAdjustment(AverageThroughput, NewWorkerThreadCount, Reason, ClrInstanceID) 0
#define FireEtwThreadPoolWorkerThreadAdjustmentStats(Duration, Throughput, ThreadWave, ThroughputWave, ThroughputErrorEstimate, AverageThroughputErrorEstimate, ThroughputRatio, Confidence, NewControlSetting, NewThreadWaveMagnitude, ClrInstanceID) 0
#define FireEtwThreadPoolWorkerThreadWait(ActiveWorkerThreadCount, RetiredWorkerThreadCount, ClrInstanceID) 0
#define FireEtwThreadPoolMinMaxThreads (MinWorkerThreads, MaxWorkerThreads, MinIOCompletionThreads, MaxIOCompletionThreads, ClrInstanceID) 0
#define FireEtwThreadPoolWorkingThreadCount(Count, ClrInstanceID) 0
#define FireEtwThreadPoolEnqueue(WorkID, ClrInstanceID) 0
#define FireEtwThreadPoolDequeue(WorkID, ClrInstanceID) 0
Expand Down
35 changes: 34 additions & 1 deletion src/coreclr/vm/ClrEtwAll.man
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,13 @@
<opcodes>
</opcodes>
</task>
<!--Next available ID is 38-->
<task name="ThreadPoolMinMaxThreads" symbol="CLR_THREADPOOLMINMAXTHREADS_TASK"
value="38" eventGUID="{6D168D67-FB06-4A60-83BA-2544E817F6A3}"
message="$(string.RuntimePublisher.ThreadPoolMinMaxThreadsTaskMessage)">
<opcodes>
</opcodes>
</task>
<!--Next available ID is 39-->
</tasks>
<!--Maps-->
<maps>
Expand Down Expand Up @@ -1579,6 +1585,24 @@
</UserData>
</template>

<template tid="ThreadPoolMinMaxThreads">
<data name="MinWorkerThreads" inType="win:UInt16" />
<data name="MaxWorkerThreads" inType="win:UInt16" />
<data name="MinIOCompletionThreads" inType="win:UInt16" />
<data name="MaxIOCompletionThreads" inType="win:UInt16" />
<data name="ClrInstanceID" inType="win:UInt16" />

<UserData>
<ThreadPoolMinMaxThreads xmlns="myNs">
<MinWorkerThreads> %1 </MinWorkerThreads>
<MaxWorkerThreads> %2 </MaxWorkerThreads>
<MinIOCompletionThreads> %3 </MinIOCompletionThreads>
<MaxIOCompletionThreads> %4 </MaxIOCompletionThreads>
<ClrInstanceID> %5 </ClrInstanceID>
</ThreadPoolMinMaxThreads>
</UserData>
</template>

<template tid="ThreadPoolWorkerThreadAdjustmentSample">
<data name="Throughput" inType="win:Double" />
<data name="ClrInstanceID" inType="win:UInt16" />
Expand Down Expand Up @@ -3455,6 +3479,13 @@
keywords="ThreadingKeyword" task="YieldProcessorMeasurement" opcode="win:Info"
symbol="YieldProcessorMeasurement" message="$(string.RuntimePublisher.YieldProcessorMeasurementEventMessage)"/>

<event value="59" version="0" level="win:Informational" template="ThreadPoolMinMaxThreads"
keywords="ThreadingKeyword"
task="ThreadPoolMinMaxThreads"
opcode="win:Info"
symbol="ThreadPoolMinMaxThreads"
message="$(string.RuntimePublisher.ThreadPoolMinMaxThreads)"/>

<!-- CLR private ThreadPool events -->
<event value="60" version="0" level="win:Verbose" template="ThreadPoolWorkingThreadCount"
keywords="ThreadingKeyword"
Expand Down Expand Up @@ -8271,6 +8302,7 @@
<string id="RuntimePublisher.WorkerThreadRetirementRetireThreadEventMessage" value="WorkerThreadCount=%1;%nRetiredWorkerThreads=%2" />
<string id="RuntimePublisher.WorkerThreadRetirementUnretireThreadEventMessage" value="WorkerThreadCount=%1;%nRetiredWorkerThreads=%2" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadEventMessage" value="WorkerThreadCount=%1;%nRetiredWorkerThreadCount=%2;%nClrInstanceID=%3" />
<string id="RuntimePublisher.ThreadPoolMinMaxThreads" value="MinWorkerThreads=%1;%nMaxWorkerThreads=%2;%nMinIOCompletionThreads=%3;%nMaxIOCompletionThreads=%4;%nClrInstanceID=%5" />
<string id="RuntimePublisher.YieldProcessorMeasurementEventMessage" value="ClrInstanceID=%1;%nNsPerYield=%2;%nEstablishedNsPerYield=%3" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadAdjustmentSampleEventMessage" value="Throughput=%1;%nClrInstanceID=%2" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadAdjustmentAdjustmentEventMessage" value="AverageThroughput=%1;%nNewWorkerThreadCount=%2;%nReason=%3;%nClrInstanceID=%4" />
Expand Down Expand Up @@ -8529,6 +8561,7 @@
<string id="RuntimePublisher.IOThreadRetirementTaskMessage" value="IOThreadRetirement" />
<string id="RuntimePublisher.ThreadpoolSuspensionTaskMessage" value="ThreadpoolSuspensionV2" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadTaskMessage" value="ThreadPoolWorkerThread" />
<string id="RuntimePublisher.ThreadPoolMinMaxThreadsTaskMessage" value="ThreadPoolMinMaxThreads" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadRetirementTaskMessage" value="ThreadPoolWorkerThreadRetirement" />
<string id="RuntimePublisher.ThreadPoolWorkerThreadAdjustmentTaskMessage" value="ThreadPoolWorkerThreadAdjustment" />
<string id="RuntimePublisher.ExceptionTaskMessage" value="Exception" />
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/vm/nativeeventsource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ extern "C" void QCALLTYPE LogThreadPoolWorkerThreadWait(_In_z_ uint activeWorker
END_QCALL;
}

extern "C" void QCALLTYPE LogThreadPoolMinMaxThreads(_In_z_ short minWorkerThreads, _In_z_ short maxWorkerThreads, _In_z_ short minIOCompletionThreads, _In_z_ short maxIOCompletionThreads, _In_z_ short clrInstanceID)
{
QCALL_CONTRACT;
BEGIN_QCALL;

FireEtwThreadPoolMinMaxThreads(minWorkerThreads, maxWorkerThreads, minIOCompletionThreads, maxIOCompletionThreads, clrInstanceID);

END_QCALL;
}

extern "C" void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentSample(_In_z_ double throughput, _In_z_ short clrInstanceID)
{
QCALL_CONTRACT;
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/nativeeventsource.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ extern "C" BOOL QCALLTYPE IsEventSourceLoggingEnabled();
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadStart(_In_z_ uint activeWorkerThreadCount, _In_z_ uint retiredWorkerThreadCount, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadStop(_In_z_ uint activeWorkerThreadCount, _In_z_ uint retiredWorkerThreadCount, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadWait(_In_z_ uint activeWorkerThreadCount, _In_z_ uint retiredWorkerThreadCount, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolMinMaxThreads(_In_z_ short minWorkerThreads, _In_z_ short maxWorkerThreads, _In_z_ short minIOCompletionThreads, _In_z_ short maxIOCompletionThreads, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentSample(_In_z_ double throughput, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentAdjustment(_In_z_ double averageThroughput, _In_z_ uint newWorkerThreadCount, _In_z_ uint reason, _In_z_ short clrInstanceID);
extern "C" void QCALLTYPE LogThreadPoolWorkerThreadAdjustmentStats(_In_z_ double duration, _In_z_ double throughput, _In_z_ double threadWave, _In_z_ double throughputWave, _In_z_ double throughputErrorEstimate, _In_z_ double AverageThroughputErrorEstimate, _In_z_ double ThroughputRatio, _In_z_ double confidence, _In_z_ double newControlSetting, _In_z_ short newThreadWaveMagnitude, _In_z_ short ClrInstanceID);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ static const Entry s_QCall[] =
DllImportEntry(LogThreadPoolWorkerThreadStart)
DllImportEntry(LogThreadPoolWorkerThreadStop)
DllImportEntry(LogThreadPoolWorkerThreadWait)
DllImportEntry(LogThreadPoolMinMaxThreads)
DllImportEntry(LogThreadPoolWorkerThreadAdjustmentSample)
DllImportEntry(LogThreadPoolWorkerThreadAdjustmentAdjustment)
DllImportEntry(LogThreadPoolWorkerThreadAdjustmentStats)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ internal sealed partial class NativeRuntimeEventSource : EventSource
private static class Messages
{
public const string WorkerThread = "ActiveWorkerThreadCount={0};\nRetiredWorkerThreadCount={1};\nClrInstanceID={2}";
public const string MinMaxThreads = "MinWorkerThreads={0};\nMaxWorkerThreads={1};\nMinIOCompletionThreads={2};\nMaxIOCompletionThreads={3};\nClrInstanceID={4}";
public const string WorkerThreadAdjustmentSample = "Throughput={0};\nClrInstanceID={1}";
public const string WorkerThreadAdjustmentAdjustment = "AverageThroughput={0};\nNewWorkerThreadCount={1};\nReason={2};\nClrInstanceID={3}";
public const string WorkerThreadAdjustmentStats = "Duration={0};\nThroughput={1};\nThreadWave={2};\nThroughputWave={3};\nThroughputErrorEstimate={4};\nAverageThroughputErrorEstimate={5};\nThroughputRatio={6};\nConfidence={7};\nNewControlSetting={8};\nNewThreadWaveMagnitude={9};\nClrInstanceID={10}";
Expand All @@ -41,6 +42,7 @@ private static class Messages
public const EventTask ThreadPoolWorkerThreadAdjustment = (EventTask)18;
public const EventTask ThreadPool = (EventTask)23;
public const EventTask ThreadPoolWorkingThreadCount = (EventTask)22;
public const EventTask ThreadPoolMinMaxThreads = (EventTask)38;
}

public static class Opcodes // this name and visibility is important for EventSource
Expand Down Expand Up @@ -248,5 +250,20 @@ private unsafe void ThreadPoolIOPack(
{
LogThreadPoolIOPack(NativeOverlapped, Overlapped, ClrInstanceID);
}


[Event(59, Level = EventLevel.Informational, Message = Messages.MinMaxThreads, Task = Tasks.ThreadPoolMinMaxThreads, Opcode = EventOpcode.Info, Version = 0, Keywords = Keywords.ThreadingKeyword)]
public unsafe void ThreadPoolMinMaxThreads(
ushort MinWorkerThreads,
ushort MaxWorkerThreads,
ushort MinIOCompletionThreads,
ushort MaxIOCompletionThreads,
ushort ClrInstanceID = DefaultClrInstanceId)
{
if (IsEnabled(EventLevel.Informational, Keywords.ThreadingKeyword))
{
LogThreadPoolMinMaxThreads(MinWorkerThreads, MaxWorkerThreads, MinIOCompletionThreads, MaxIOCompletionThreads, ClrInstanceID);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static class Keywords
private static class Messages
{
public const string WorkerThread = "ActiveWorkerThreadCount={0};\nRetiredWorkerThreadCount={1};\nClrInstanceID={2}";
public const string MinMaxThreads = "MinWorkerThreads={0};\nMaxWorkerThreads={1};\nMinIOCompletionThreads={2};\nMaxIOCompletionThreads={3};\nClrInstanceID={4}";
public const string WorkerThreadAdjustmentSample = "Throughput={0};\nClrInstanceID={1}";
public const string WorkerThreadAdjustmentAdjustment = "AverageThroughput={0};\nNewWorkerThreadCount={1};\nReason={2};\nClrInstanceID={3}";
public const string WorkerThreadAdjustmentStats = "Duration={0};\nThroughput={1};\nThreadWave={2};\nThroughputWave={3};\nThroughputErrorEstimate={4};\nAverageThroughputErrorEstimate={5};\nThroughputRatio={6};\nConfidence={7};\nNewControlSetting={8};\nNewThreadWaveMagnitude={9};\nClrInstanceID={10}";
Expand All @@ -44,6 +45,7 @@ private static class Messages
public const EventTask ThreadPoolWorkerThreadAdjustment = (EventTask)18;
public const EventTask ThreadPool = (EventTask)23;
public const EventTask ThreadPoolWorkingThreadCount = (EventTask)22;
public const EventTask ThreadPoolMinMaxThreads = (EventTask)38;
}

public static class Opcodes // this name and visibility is important for EventSource
Expand Down Expand Up @@ -398,5 +400,42 @@ private unsafe void ThreadPoolIOPack(
data[2].Reserved = 0;
WriteEventCore(65, 3, data);
}


#if !ES_BUILD_STANDALONE
[System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
Justification = EventSourceSuppressMessage)]
#endif
[Event(59, Level = EventLevel.Informational, Message = Messages.MinMaxThreads, Task = Tasks.ThreadPoolMinMaxThreads, Opcode = EventOpcode.Info, Version = 0, Keywords = Keywords.ThreadingKeyword)]
public unsafe void ThreadPoolMinMaxThreads(
ushort MinWorkerThreads,
ushort MaxWorkerThreads,
ushort MinIOCompletionThreads,
ushort MaxIOCompletionThreads,
ushort ClrInstanceID = DefaultClrInstanceId)
{
if (!IsEnabled(EventLevel.Informational, Keywords.ThreadingKeyword))
{
return;
}
EventData* data = stackalloc EventData[5];
data[0].DataPointer = (IntPtr)(&MinWorkerThreads);
data[0].Size = sizeof(ushort);
data[0].Reserved = 0;
data[1].DataPointer = (IntPtr)(&MaxWorkerThreads);
data[1].Size = sizeof(ushort);
data[1].Reserved = 0;
data[2].DataPointer = (IntPtr)(&MinIOCompletionThreads);
data[2].Size = sizeof(ushort);
data[2].Reserved = 0;
data[3].DataPointer = (IntPtr)(&MaxIOCompletionThreads);
data[3].Size = sizeof(ushort);
data[3].Reserved = 0;
data[4].DataPointer = (IntPtr)(&ClrInstanceID);
data[4].Size = sizeof(ushort);
data[4].Reserved = 0;
WriteEventCore(59, 5, data);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

Expand Down Expand Up @@ -111,6 +112,15 @@ private PortableThreadPool()
_legacy_minIOCompletionThreads = 1;
_legacy_maxIOCompletionThreads = 1000;

if (NativeRuntimeEventSource.Log.IsEnabled())
{
NativeRuntimeEventSource.Log.ThreadPoolMinMaxThreads(
(ushort)_minThreads,
(ushort)_maxThreads,
(ushort)_legacy_minIOCompletionThreads,
(ushort)_legacy_maxIOCompletionThreads);
}

_separated.counts.NumThreadsGoal = _minThreads;

#if TARGET_WINDOWS
Expand Down Expand Up @@ -186,6 +196,15 @@ public bool SetMinThreads(int workerThreads, int ioCompletionThreads)
addWorker = true;
}
}

if (NativeRuntimeEventSource.Log.IsEnabled())
{
NativeRuntimeEventSource.Log.ThreadPoolMinMaxThreads(
(ushort)_minThreads,
(ushort)_maxThreads,
(ushort)_legacy_minIOCompletionThreads,
(ushort)_legacy_maxIOCompletionThreads);
}
}
finally
{
Expand Down Expand Up @@ -256,6 +275,15 @@ public bool SetMaxThreads(int workerThreads, int ioCompletionThreads)
{
_separated.counts.InterlockedSetNumThreadsGoal(newMaxThreads);
}

if (NativeRuntimeEventSource.Log.IsEnabled())
{
NativeRuntimeEventSource.Log.ThreadPoolMinMaxThreads(
(ushort)_minThreads,
(ushort)_maxThreads,
(ushort)_legacy_minIOCompletionThreads,
(ushort)_legacy_maxIOCompletionThreads);
}
return true;
}
finally
Expand Down
Loading

0 comments on commit 41d9c1c

Please sign in to comment.