-
Notifications
You must be signed in to change notification settings - Fork 680
Add global worker statistics param (QUIC_PARAM_GLOBAL_WORKER_STATISTICS) #6115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
c4af934
3a92d5e
b8e81fb
613e221
cf68e51
58bb6d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -102,6 +102,27 @@ typedef struct QUIC_CACHEALIGN CXPLAT_WORKER { | |
| // | ||
| BOOLEAN Running; | ||
|
|
||
| // | ||
| // Statistics tracking for active time measurement. | ||
| // | ||
| struct { | ||
| // | ||
| // Timestamp (in microseconds) when the worker thread started. | ||
| // | ||
| uint64_t StartedTimeUs; | ||
|
|
||
| // | ||
| // Timestamp (in microseconds) when the current active period started, | ||
| // or 0 when the worker is currently idle (waiting or yielding). | ||
| // | ||
| uint64_t ActiveStartTimeUs; | ||
|
|
||
| // | ||
| // Cumulative time (in microseconds) the worker was active (not waiting or yielding). | ||
| // | ||
| uint64_t CumulativeActiveTimeUs; | ||
| } Stats; | ||
|
|
||
| } CXPLAT_WORKER; | ||
|
|
||
| typedef struct CXPLAT_WORKER_POOL { | ||
|
|
@@ -728,18 +749,55 @@ CxPlatProcessDynamicPoolAllocators( | |
| CxPlatLockRelease(&Worker->ECLock); | ||
| } | ||
|
|
||
| // | ||
| // Marks the end of an active period, folding the elapsed active time into the | ||
| // cumulative total and marking the worker idle (ActiveStartTimeUs == 0). | ||
| // | ||
| void | ||
| CxPlatWorkerStatsPause( | ||
| _Inout_ CXPLAT_WORKER* Worker | ||
| ) | ||
| { | ||
| if (Worker->Stats.ActiveStartTimeUs != 0) { | ||
| Worker->Stats.CumulativeActiveTimeUs += | ||
| CxPlatTimeDiff64(Worker->Stats.ActiveStartTimeUs, CxPlatTimeUs64()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally, looks fine, but you need to be careful with all the
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The timestamp in the worker loop is snapped again only after the events have been processed. I considered re-ordering the loop so that
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at it again, we currently snap time:
Both are potentially time consuming, so it seems reasonable to me to snap the time again - at least because the ECs seems to need a pretty fresh timestamp (see the comment about solving a potential race, it isn't clear which race this is but I suspect it has something to do with timers being already expired). |
||
| Worker->Stats.ActiveStartTimeUs = 0; | ||
| } | ||
| } | ||
|
|
||
| // | ||
| // Marks the start of an active period. | ||
| // | ||
| void | ||
| CxPlatWorkerStatsResume( | ||
| _Inout_ CXPLAT_WORKER* Worker | ||
| ) | ||
| { | ||
| Worker->Stats.ActiveStartTimeUs = CxPlatTimeUs64(); | ||
| } | ||
|
|
||
| void | ||
| CxPlatProcessEvents( | ||
| _In_ CXPLAT_WORKER* Worker | ||
| ) | ||
| { | ||
| CXPLAT_CQE Cqes[16]; | ||
|
|
||
| if (Worker->State.WaitTime > 0) { | ||
| CxPlatWorkerStatsPause(Worker); | ||
| } | ||
|
|
||
| uint32_t CqeCount = | ||
| CxPlatEventQDequeue( | ||
| &Worker->EventQ, | ||
| Cqes, | ||
| ARRAYSIZE(Cqes), | ||
| Worker->State.WaitTime); | ||
|
|
||
| if (Worker->State.WaitTime > 0) { | ||
| CxPlatWorkerStatsResume(Worker); | ||
| } | ||
|
|
||
| uint32_t CurrentCqeCount = CqeCount; | ||
| CXPLAT_CQE* CurrentCqe = Cqes; | ||
|
|
||
|
|
@@ -796,6 +854,8 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context) | |
|
|
||
| Worker->State.ThreadID = CxPlatCurThreadID(); | ||
| Worker->Running = TRUE; | ||
| Worker->Stats.StartedTimeUs = CxPlatTimeUs64(); | ||
| Worker->Stats.ActiveStartTimeUs = Worker->Stats.StartedTimeUs; | ||
|
|
||
| while (!Worker->StoppedThread) { | ||
|
|
||
|
|
@@ -816,7 +876,9 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context) | |
| if (Worker->State.NoWorkCount == 0) { | ||
| Worker->State.LastWorkTime = Worker->State.TimeNow; | ||
| } else if (Worker->State.NoWorkCount > CXPLAT_WORKER_IDLE_WORK_THRESHOLD_COUNT) { | ||
| CxPlatWorkerStatsPause(Worker); | ||
| CxPlatSchedulerYield(); | ||
| CxPlatWorkerStatsResume(Worker); | ||
| Worker->State.NoWorkCount = 0; | ||
| } | ||
|
|
||
|
|
@@ -826,6 +888,7 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context) | |
| } | ||
| } | ||
|
|
||
| CxPlatWorkerStatsPause(Worker); | ||
| Worker->Running = FALSE; | ||
|
|
||
| #if DEBUG | ||
|
|
@@ -839,3 +902,28 @@ CXPLAT_THREAD_CALLBACK(CxPlatWorkerThread, Context) | |
|
|
||
| CXPLAT_THREAD_RETURN(0); | ||
| } | ||
|
|
||
| void | ||
| CxPlatWorkerPoolGetStatistics( | ||
| _In_ CXPLAT_WORKER_POOL* WorkerPool, | ||
| _In_ uint32_t Index, | ||
| _Out_ CXPLAT_WORKER_STATISTICS* Stats | ||
| ) | ||
| { | ||
| CXPLAT_FRE_ASSERT(Index < WorkerPool->WorkerCount); | ||
|
|
||
| const uint64_t Now = CxPlatTimeUs64(); | ||
|
guhetier marked this conversation as resolved.
Outdated
|
||
| CXPLAT_WORKER* Worker = &WorkerPool->Workers[Index]; | ||
|
|
||
| Stats->IdealProcessor = Worker->IdealProcessor; | ||
| Stats->CumulativeWallTimeUs = CxPlatTimeDiff64(Worker->Stats.StartedTimeUs, Now); | ||
| Stats->CumulativeActiveTimeUs = Worker->Stats.CumulativeActiveTimeUs; | ||
|
|
||
| // | ||
| // If the worker is currently active, include the in-progress active period. | ||
| // | ||
| const uint64_t ActiveStartTimeUs = Worker->Stats.ActiveStartTimeUs; | ||
| if (ActiveStartTimeUs != 0 && ActiveStartTimeUs < Now) { | ||
| Stats->CumulativeActiveTimeUs += CxPlatTimeDiff64(ActiveStartTimeUs, Now); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.