-
Notifications
You must be signed in to change notification settings - Fork 25.6k
Time framed thread-pool utilization #131898
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 22 commits
18ec741
80f792f
8345da4
2421600
cb531b9
ab04cc6
deea172
454a871
5228abd
a87a7c4
8850789
3d66e86
efa48b4
872d7cd
33173fb
f3c81db
c281e8d
5771c46
12ef5e4
d006ed5
3caae03
18115c4
3816a50
fd0b91a
225280a
36374fc
3dd755e
0fbbd81
c1c33ac
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 |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the "Elastic License | ||
| * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
| * Public License v 1"; you may not use this file except in compliance with, at | ||
| * your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
|
|
||
| package org.elasticsearch.benchmark.common.util.concurrent; | ||
|
|
||
| import org.elasticsearch.common.util.concurrent.TaskExecutionTimeTrackingEsThreadPoolExecutor; | ||
| import org.openjdk.jmh.annotations.Benchmark; | ||
| import org.openjdk.jmh.annotations.BenchmarkMode; | ||
| import org.openjdk.jmh.annotations.Fork; | ||
| import org.openjdk.jmh.annotations.Group; | ||
| import org.openjdk.jmh.annotations.Measurement; | ||
| import org.openjdk.jmh.annotations.Mode; | ||
| import org.openjdk.jmh.annotations.OutputTimeUnit; | ||
| import org.openjdk.jmh.annotations.Param; | ||
| import org.openjdk.jmh.annotations.Scope; | ||
| import org.openjdk.jmh.annotations.Setup; | ||
| import org.openjdk.jmh.annotations.State; | ||
| import org.openjdk.jmh.annotations.Threads; | ||
| import org.openjdk.jmh.annotations.Warmup; | ||
| import org.openjdk.jmh.infra.Blackhole; | ||
|
|
||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| @Threads(Threads.MAX) | ||
| @Warmup(iterations = 3, time = 200, timeUnit = TimeUnit.MILLISECONDS) | ||
| @Measurement(iterations = 1, time = 60, timeUnit = TimeUnit.SECONDS) | ||
| @BenchmarkMode(Mode.SampleTime) | ||
| @OutputTimeUnit(TimeUnit.MICROSECONDS) | ||
| @State(Scope.Benchmark) | ||
| @Fork(1) | ||
| public class ThreadPoolUtilizationBenchmark { | ||
|
|
||
| @Param({ "10000" }) | ||
| private int callIntervalTicks; | ||
|
|
||
| /** | ||
| * This makes very little difference, all the overhead is in the synchronization | ||
| */ | ||
| @Param({ "100" }) | ||
| private int utilizationIntervalMs; | ||
| private TaskExecutionTimeTrackingEsThreadPoolExecutor.FramedTimeTracker timeTracker; | ||
|
|
||
| @Setup | ||
| public void setup() { | ||
| timeTracker = new TaskExecutionTimeTrackingEsThreadPoolExecutor.FramedTimeTracker( | ||
| TimeUnit.MILLISECONDS.toNanos(utilizationIntervalMs), | ||
| System::nanoTime | ||
| ); | ||
| } | ||
|
|
||
| @Benchmark | ||
| public void baseline() { | ||
| Blackhole.consumeCPU(callIntervalTicks); | ||
| } | ||
|
|
||
| @Group("StartAndEnd") | ||
| @Benchmark | ||
| public void startAndStopTasks() { | ||
| timeTracker.startTask(); | ||
| Blackhole.consumeCPU(callIntervalTicks); | ||
| timeTracker.endTask(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| pr: 131898 | ||
| summary: Time framed thread-pool utilization | ||
| area: Allocation | ||
| type: enhancement | ||
| issues: [] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |
| import org.elasticsearch.core.SuppressForbidden; | ||
| import org.elasticsearch.node.Node; | ||
|
|
||
| import java.time.Duration; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.concurrent.AbstractExecutorService; | ||
|
|
@@ -576,80 +577,72 @@ public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) { | |
| } | ||
| } | ||
|
|
||
| public static class TaskTrackingConfig { | ||
| /** | ||
| * @param trackExecutionTime Whether to track execution stats | ||
| * @param trackUtilization enables thread-pool utilization metrics | ||
| * @param utilizationInterval when utilization is enabled, specifies interval for measurement | ||
| * @param trackOngoingTasks Whether to track ongoing task execution time, not just finished tasks | ||
| * @param trackMaxQueueLatency Whether to track max queue latency. | ||
| * @param executionTimeEwmaAlpha The alpha seed for execution time EWMA (ExponentiallyWeightedMovingAverage). | ||
|
||
| */ | ||
| public record TaskTrackingConfig( | ||
| boolean trackExecutionTime, | ||
| boolean trackUtilization, | ||
| Duration utilizationInterval, | ||
| boolean trackOngoingTasks, | ||
| boolean trackMaxQueueLatency, | ||
| double executionTimeEwmaAlpha | ||
| ) { | ||
|
|
||
| // This is a random starting point alpha. | ||
| public static final double DEFAULT_EXECUTION_TIME_EWMA_ALPHA_FOR_TEST = 0.3; | ||
|
|
||
| private final boolean trackExecutionTime; | ||
| private final boolean trackOngoingTasks; | ||
| private final boolean trackMaxQueueLatency; | ||
| private final double executionTimeEwmaAlpha; | ||
| public static final Duration DEFAULT_UTILIZATION_INTERVAL = Duration.ofSeconds(30); | ||
|
|
||
| public static final TaskTrackingConfig DO_NOT_TRACK = new TaskTrackingConfig( | ||
| false, | ||
| false, | ||
| DEFAULT_UTILIZATION_INTERVAL, | ||
| false, | ||
| false, | ||
| DEFAULT_EXECUTION_TIME_EWMA_ALPHA_FOR_TEST | ||
| ); | ||
|
|
||
| public static final TaskTrackingConfig DEFAULT = new TaskTrackingConfig( | ||
| true, | ||
| true, | ||
| DEFAULT_UTILIZATION_INTERVAL, | ||
| false, | ||
| false, | ||
| DEFAULT_EXECUTION_TIME_EWMA_ALPHA_FOR_TEST | ||
| ); | ||
|
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. I know this is peripheral but I think we should move to using the builder for |
||
|
|
||
| /** | ||
| * @param trackExecutionTime Whether to track execution stats | ||
| * @param trackOngoingTasks Whether to track ongoing task execution time, not just finished tasks | ||
| * @param trackMaxQueueLatency Whether to track max queue latency. | ||
| * @param executionTimeEWMAAlpha The alpha seed for execution time EWMA (ExponentiallyWeightedMovingAverage). | ||
| */ | ||
| private TaskTrackingConfig( | ||
| boolean trackExecutionTime, | ||
| boolean trackOngoingTasks, | ||
| boolean trackMaxQueueLatency, | ||
| double executionTimeEWMAAlpha | ||
| ) { | ||
| this.trackExecutionTime = trackExecutionTime; | ||
| this.trackOngoingTasks = trackOngoingTasks; | ||
| this.trackMaxQueueLatency = trackMaxQueueLatency; | ||
| this.executionTimeEwmaAlpha = executionTimeEWMAAlpha; | ||
| } | ||
|
|
||
| public boolean trackExecutionTime() { | ||
| return trackExecutionTime; | ||
| } | ||
|
|
||
| public boolean trackOngoingTasks() { | ||
| return trackOngoingTasks; | ||
| } | ||
|
|
||
| public boolean trackMaxQueueLatency() { | ||
| return trackMaxQueueLatency; | ||
| } | ||
|
|
||
| public double getExecutionTimeEwmaAlpha() { | ||
| return executionTimeEwmaAlpha; | ||
| } | ||
|
|
||
| public static Builder builder() { | ||
| return new Builder(); | ||
| } | ||
|
|
||
| public static class Builder { | ||
| private boolean trackExecutionTime = false; | ||
| private boolean trackUtilization = false; | ||
| private boolean trackOngoingTasks = false; | ||
| private boolean trackMaxQueueLatency = false; | ||
| private double ewmaAlpha = DEFAULT_EXECUTION_TIME_EWMA_ALPHA_FOR_TEST; | ||
| private Duration utilizationInterval = DEFAULT_UTILIZATION_INTERVAL; | ||
|
|
||
| public Builder() {} | ||
|
|
||
| public Builder trackExecutionTime(double alpha) { | ||
| trackExecutionTime = true; | ||
| trackUtilization = true; | ||
| ewmaAlpha = alpha; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder trackUtilization(Duration interval) { | ||
| trackUtilization = true; | ||
| utilizationInterval = interval; | ||
| return this; | ||
| } | ||
|
|
||
| public Builder trackOngoingTasks() { | ||
| trackOngoingTasks = true; | ||
| return this; | ||
|
|
@@ -661,7 +654,14 @@ public Builder trackMaxQueueLatency() { | |
| } | ||
|
|
||
| public TaskTrackingConfig build() { | ||
| return new TaskTrackingConfig(trackExecutionTime, trackOngoingTasks, trackMaxQueueLatency, ewmaAlpha); | ||
| return new TaskTrackingConfig( | ||
| trackExecutionTime, | ||
| trackUtilization, | ||
| utilizationInterval, | ||
| trackOngoingTasks, | ||
| trackMaxQueueLatency, | ||
| ewmaAlpha | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.