24.8.8 Backport PR #68674 Thread pool metrics #567
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Original PR:
ClickHouse#68674
Changelog Category:
Changelog Entry:
Added a new set of metrics for Thread Pool introspection, providing deeper insights into thread pool performance and behavior.
Documentation Entry for User-Facing Changes
Several new metrics have been introduced to enhance monitoring and analysis of thread pools:
Obsolete Metrics: The
LocalThread
,LocalThreadActive
, andLocalThreadScheduled
metrics have been marked as obsolete. This change reflects recent architectural updates that reduce the relevance of local thread pools, as discussed in ClickHouse PR #47880. Users should adjust their monitoring configurations accordingly.GlobalThreadPoolExpansions and Shrinks: These metrics track the frequency of expansions and contractions in the global thread pool, offering visibility into how the system adapts to varying workloads.
Thread Creation and Lock Wait Times: These metrics measure the time taken to start new threads and the time threads spend waiting for locks. These insights are crucial for identifying potential bottlenecks in thread management.
Job Wait Time: This metric captures the time elapsed from when a job is scheduled until it is executed, providing a clear view of the responsiveness of the thread pool.
Additionally, to prevent jobs from being delayed or stuck in the queue, the job queue within the
ThreadPool
has been made stable. This ensures that jobs with the same priority are processed in the order they were added, enabling fair and timely execution. While I don't have a test showing any issues caused by the previous queue behavior (non-FIFO), the problems with that were observed during experiments with modified code.Key Metrics to Monitor
GlobalThreadPoolThreadCreationMicroseconds: Normally low, and even thousands of threads can created per second without delays. However, under certain conditions, thread creation can be slow, potentially due to kernel-level locks around memory maps (unconfirmed). When that metric increases is have cascading effect on lock waits & JobWaitTime, and underperforming thread pool.
GlobalThreadPoolExpansions and Shrinks: Ideally, these should not happen too often, indicating that the global pool size is well-tuned for the workload.
GlobalThreadPoolJobs and LocalThreadPoolJobs: Indicate the number of jobs processed by the thread pools, providing a sense of workload distribution.
LocalThreadPoolJobWaitTimeMicroseconds and GlobalThreadPoolJobWaitTimeMicroseconds: These metrics signal delays in the ThreadPool queue, which could be due to locks, out-of-order execution, cpu starvation, or other factors.
GlobalThreadPoolLockWaitMicroseconds and LocalThreadPoolLockWaitMicroseconds: These metrics allow for analysis of lock contention, with values proportional to the number of active threads waiting for the lock.
LocalThreadPoolBusyMicroseconds: When compared to
LocalThreadPoolJobWaitTimeMicroseconds
, this metric helps assess how efficiently the thread pool is operating, highlighting the balance between useful work and thread pool maintenance overhead.LocalThreadPoolThreadCreationMicroseconds is actually time used to push the task into the GlobalThread pool (can be impacted by locks, and slow creation of the 'real' threads).
Note: The counter metrics will only be partially visible in the
system.query_log
underProfileEvents
. Specifically, only those metrics incremented in the::scheduleImpl
method will be logged. This is because counters incremented in the::worker
method occur before the thread status is initialized, making them visible only in the global context and not on a per-query basis.For practical examples and test results, you can refer to the following test.
Sample Output
In that synthetic test the pool efficiency was only 55%, 45% of time was just wasted on thread pool management.
Another (indirect) signal of the problems is how many threads have actually task to do - just by looking on the thread names (threads which don't have an actual job are named
ThreadPool
):Or by comparing the number of working threads, vs active threads: