diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-09-07 15:06:24 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-09-07 17:53:16 +0200 |
commit | ab8b4e97ccea563b3e481e59a689f1f9d5b2386f (patch) | |
tree | 47e878e46c90b08b7073ed6b888dfbcd9e5b2bcf | |
parent | 4c5492d00a012b833fe24decb72c5c54f690fd79 (diff) |
Use separate non-public config definition for ContainerThreadPool
6 files changed, 70 insertions, 28 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ThreadPoolExecutorComponent.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ThreadPoolExecutorComponent.java index aac73ce7636..9d59941f603 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ThreadPoolExecutorComponent.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ThreadPoolExecutorComponent.java @@ -2,8 +2,8 @@ package com.yahoo.vespa.model.container; import com.yahoo.container.bundle.BundleInstantiationSpecification; -import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.container.handler.threadpool.ContainerThreadPool; +import com.yahoo.container.handler.threadpool.ContainerThreadpoolConfig; import com.yahoo.osgi.provider.model.ComponentModel; import com.yahoo.vespa.model.container.component.SimpleComponent; @@ -14,7 +14,7 @@ import java.time.Duration; * * @author bjorncs */ -public class ThreadPoolExecutorComponent extends SimpleComponent implements ThreadpoolConfig.Producer { +public class ThreadPoolExecutorComponent extends SimpleComponent implements ContainerThreadpoolConfig.Producer { private final String name; private final Integer maxPoolSize; @@ -38,10 +38,10 @@ public class ThreadPoolExecutorComponent extends SimpleComponent implements Thre } @Override - public void getConfig(ThreadpoolConfig.Builder builder) { + public void getConfig(ContainerThreadpoolConfig.Builder builder) { builder.name(this.name); - if (maxPoolSize != null) builder.maxthreads(maxPoolSize); - if (corePoolSize != null) builder.corePoolSize(corePoolSize); + if (maxPoolSize != null) builder.maxThreads(maxPoolSize); + if (corePoolSize != null) builder.minThreads(corePoolSize); if (keepAliveTime != null) builder.keepAliveTime(keepAliveTime.toMillis() / 1000D); if (queueSize != null) builder.queueSize(queueSize); if (maxThreadExecutionTime != null) builder.maxThreadExecutionTimeSeconds((int)maxThreadExecutionTime.toMillis() / 1000); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java index ab73309bb7d..93117821c5a 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java @@ -12,7 +12,7 @@ import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.HostSpec; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.ProvisionLogger; -import com.yahoo.container.handler.ThreadpoolConfig; +import com.yahoo.container.handler.threadpool.ContainerThreadpoolConfig; import com.yahoo.net.HostName; import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.component.Handler; @@ -115,9 +115,10 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa Set<String> injectedComponentIds = feedApiHandler.getInjectedComponentIds(); assertThat(injectedComponentIds, hasItem("threadpool@feedapi-handler")); - ThreadpoolConfig config = root.getConfig(ThreadpoolConfig.class, "cluster1/component/com.yahoo.vespa.http.server.FeedHandler/threadpool@feedapi-handler"); - assertEquals(16, config.maxthreads()); - assertEquals(8, config.corePoolSize()); + ContainerThreadpoolConfig config = root.getConfig( + ContainerThreadpoolConfig.class, "cluster1/component/com.yahoo.vespa.http.server.FeedHandler/threadpool@feedapi-handler"); + assertEquals(16, config.maxThreads()); + assertEquals(8, config.minThreads()); } private static class HostProvisionerWithCustomRealResource implements HostProvisioner { diff --git a/container-core/src/main/java/com/yahoo/container/handler/ThreadPoolProvider.java b/container-core/src/main/java/com/yahoo/container/handler/ThreadPoolProvider.java index 425387039ff..dc594903f21 100644 --- a/container-core/src/main/java/com/yahoo/container/handler/ThreadPoolProvider.java +++ b/container-core/src/main/java/com/yahoo/container/handler/ThreadPoolProvider.java @@ -5,6 +5,7 @@ import com.google.inject.Inject; import com.yahoo.component.AbstractComponent; import com.yahoo.container.di.componentgraph.Provider; import com.yahoo.container.handler.threadpool.ContainerThreadPool; +import com.yahoo.container.handler.threadpool.ContainerThreadpoolConfig; import com.yahoo.container.protect.ProcessTerminator; import com.yahoo.jdisc.Metric; @@ -23,12 +24,27 @@ public class ThreadPoolProvider extends AbstractComponent implements Provider<Ex private final ContainerThreadPool threadpool; @Inject - public ThreadPoolProvider(ThreadpoolConfig threadpoolConfig, Metric metric) { - this.threadpool = new ContainerThreadPool(threadpoolConfig, metric); + public ThreadPoolProvider(ThreadpoolConfig config, Metric metric) { + this.threadpool = new ContainerThreadPool(translateConfig(config), metric); } - public ThreadPoolProvider(ThreadpoolConfig threadpoolConfig, Metric metric, ProcessTerminator processTerminator) { - this.threadpool = new ContainerThreadPool(threadpoolConfig, metric, processTerminator); + public ThreadPoolProvider(ThreadpoolConfig config, Metric metric, ProcessTerminator processTerminator) { + this.threadpool = new ContainerThreadPool(translateConfig(config), metric, processTerminator); + } + + /** + * The underlying {@link ContainerThreadPool} uses a different config definition ({@link ContainerThreadpoolConfig}) + * as {@link ThreadpoolConfig} is currently public api. + */ + private static ContainerThreadpoolConfig translateConfig(ThreadpoolConfig config) { + return new ContainerThreadpoolConfig( + new ContainerThreadpoolConfig.Builder() + .maxThreads(config.maxthreads()) + .minThreads(config.corePoolSize()) + .name(config.name()) + .queueSize(config.queueSize()) + .keepAliveTime(config.keepAliveTime()) + .maxThreadExecutionTimeSeconds(config.maxThreadExecutionTimeSeconds())); } /** diff --git a/container-core/src/main/java/com/yahoo/container/handler/threadpool/ContainerThreadPool.java b/container-core/src/main/java/com/yahoo/container/handler/threadpool/ContainerThreadPool.java index 74bcb3a2e04..e2d38427de1 100644 --- a/container-core/src/main/java/com/yahoo/container/handler/threadpool/ContainerThreadPool.java +++ b/container-core/src/main/java/com/yahoo/container/handler/threadpool/ContainerThreadPool.java @@ -4,7 +4,6 @@ package com.yahoo.container.handler.threadpool; import com.google.inject.Inject; import com.yahoo.component.AbstractComponent; import com.yahoo.concurrent.ThreadFactoryFactory; -import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.container.protect.ProcessTerminator; import com.yahoo.jdisc.Metric; @@ -27,26 +26,26 @@ public class ContainerThreadPool extends AbstractComponent implements AutoClosea private final ExecutorServiceWrapper threadpool; @Inject - public ContainerThreadPool(ThreadpoolConfig config, Metric metric) { + public ContainerThreadPool(ContainerThreadpoolConfig config, Metric metric) { this(config, metric, new ProcessTerminator()); } - public ContainerThreadPool(ThreadpoolConfig threadpoolConfig, Metric metric, ProcessTerminator processTerminator) { - ThreadPoolMetric threadPoolMetric = new ThreadPoolMetric(metric, threadpoolConfig.name()); - int maxNumThreads = computeMaximumThreadPoolSize(threadpoolConfig.maxthreads()); - int coreNumThreads = computeCoreThreadPoolSize(threadpoolConfig.corePoolSize(), maxNumThreads); + public ContainerThreadPool(ContainerThreadpoolConfig config, Metric metric, ProcessTerminator processTerminator) { + ThreadPoolMetric threadPoolMetric = new ThreadPoolMetric(metric, config.name()); + int maxNumThreads = computeMaximumThreadPoolSize(config.maxThreads()); + int coreNumThreads = computeCoreThreadPoolSize(config.minThreads(), maxNumThreads); WorkerCompletionTimingThreadPoolExecutor executor = new WorkerCompletionTimingThreadPoolExecutor(coreNumThreads, maxNumThreads, - (int)threadpoolConfig.keepAliveTime() * 1000, TimeUnit.MILLISECONDS, - createQ(threadpoolConfig.queueSize(), maxNumThreads), - ThreadFactoryFactory.getThreadFactory(threadpoolConfig.name()), + (int)config.keepAliveTime() * 1000, TimeUnit.MILLISECONDS, + createQ(config.queueSize(), maxNumThreads), + ThreadFactoryFactory.getThreadFactory(config.name()), threadPoolMetric); // Prestart needed, if not all threads will be created by the fist N tasks and hence they might also // get the dreaded thread locals initialized even if they will never run. // That counters what we we want to achieve with the Q that will prefer thread locality. executor.prestartAllCoreThreads(); threadpool = new ExecutorServiceWrapper(executor, threadPoolMetric, processTerminator, - threadpoolConfig.maxThreadExecutionTimeSeconds() * 1000L); + config.maxThreadExecutionTimeSeconds() * 1000L); } public Executor executor() { return threadpool; } diff --git a/container-core/src/main/resources/configdefinitions/container-threadpool.def b/container-core/src/main/resources/configdefinitions/container-threadpool.def new file mode 100644 index 00000000000..9248bf2e2bf --- /dev/null +++ b/container-core/src/main/resources/configdefinitions/container-threadpool.def @@ -0,0 +1,25 @@ +# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +namespace=container.handler.threadpool + +## Maximum number of thread in the thread pool +## 0 is translated to vcpu*4 +maxThreads int default=0 + +## Minimum number of thread in the thread pool +## 0 is translated to vcpu*2 +minThreads int default=0 + +## The number of seconds that excess idle threads will wait for new tasks before terminating +keepAliveTime double default=5.0 + +## Max queue size +queueSize int default=0 + +## The max time the container tolerates having no threads available before it shuts down to +## get out of a bad state. This should be set a bit higher than the expected max execution +## time of each request when in a state of overload, i.e about "worst case execution time*2" +maxThreadExecutionTimeSeconds int default=190 + +# Prefix for the name of the threads +name string default="default-pool" diff --git a/container-core/src/test/java/com/yahoo/container/handler/threadpool/ContainerThreadPoolTest.java b/container-core/src/test/java/com/yahoo/container/handler/threadpool/ContainerThreadPoolTest.java index f6a3aebd7ff..02e791099ed 100644 --- a/container-core/src/test/java/com/yahoo/container/handler/threadpool/ContainerThreadPoolTest.java +++ b/container-core/src/test/java/com/yahoo/container/handler/threadpool/ContainerThreadPoolTest.java @@ -3,7 +3,6 @@ package com.yahoo.container.handler.threadpool; import com.yahoo.collections.Tuple2; import com.yahoo.concurrent.Receiver; -import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.container.protect.ProcessTerminator; import com.yahoo.jdisc.Metric; import org.junit.Ignore; @@ -24,7 +23,7 @@ import static org.junit.Assert.fail; public class ContainerThreadPoolTest { @Test public final void testThreadPool() throws InterruptedException { - ThreadpoolConfig config = new ThreadpoolConfig(new ThreadpoolConfig.Builder().maxthreads(1)); + ContainerThreadpoolConfig config = new ContainerThreadpoolConfig(new ContainerThreadpoolConfig.Builder().maxThreads(1)); ContainerThreadPool threadPool = new ContainerThreadPool(config, Mockito.mock(Metric.class)); Executor exec = threadPool.executor(); Tuple2<Receiver.MessageState, Boolean> reply; @@ -56,7 +55,7 @@ public class ContainerThreadPoolTest { } private ThreadPoolExecutor createPool(int maxThreads, int queueSize) { - ThreadpoolConfig config = new ThreadpoolConfig(new ThreadpoolConfig.Builder().maxthreads(maxThreads).queueSize(queueSize)); + ContainerThreadpoolConfig config = new ContainerThreadpoolConfig(new ContainerThreadpoolConfig.Builder().maxThreads(maxThreads).queueSize(queueSize)); ContainerThreadPool threadPool = new ContainerThreadPool(config, Mockito.mock(Metric.class)); ExecutorServiceWrapper wrapper = (ExecutorServiceWrapper) threadPool.executor(); WorkerCompletionTimingThreadPoolExecutor executor = (WorkerCompletionTimingThreadPoolExecutor)wrapper.delegate(); @@ -100,8 +99,10 @@ public class ContainerThreadPoolTest { @Test @Ignore // Ignored because it depends on the system time and so is unstable on factory public void testThreadPoolTerminationOnBreakdown() throws InterruptedException { - ThreadpoolConfig config = new ThreadpoolConfig(new ThreadpoolConfig.Builder().maxthreads(2) - .maxThreadExecutionTimeSeconds(1)); + ContainerThreadpoolConfig config = new ContainerThreadpoolConfig( + new ContainerThreadpoolConfig.Builder() + .maxThreads(2) + .maxThreadExecutionTimeSeconds(1)); MockProcessTerminator terminator = new MockProcessTerminator(); ContainerThreadPool threadPool = new ContainerThreadPool(config, Mockito.mock(Metric.class), terminator); |