From c7b890535a3009e52e7227b883f2c9a16e59a740 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Sat, 25 Apr 2020 18:57:12 +0000 Subject: Let size of thread pool and Q follow number of cores on the machine where it is running. If auto detected num worker threads will use number of #cores * 4, quesize will use #numWorkers * 4. No changes of the default value in this commit. --- .../yahoo/config/model/deploy/TestProperties.java | 20 +++++++++++ .../model/container/ApplicationContainer.java | 18 +++++++++- .../vespa/model/container/ContainerCluster.java | 14 ++++++++ .../vespa/model/container/NodeFlavorTuning.java | 30 ++++++++++++++++- .../model/container/ContainerClusterTest.java | 39 ++++++++++++++++++++++ 5 files changed, 119 insertions(+), 2 deletions(-) (limited to 'config-model/src') diff --git a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java index 99225beba4f..d799af36c3b 100644 --- a/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java +++ b/config-model/src/main/java/com/yahoo/config/model/deploy/TestProperties.java @@ -43,6 +43,8 @@ public class TestProperties implements ModelContext.Properties { private double topKProbability = 1.0; private double defaultTermwiseLimit = 1.0; private double softStartSeconds = 0.0; + private double threadPoolSizeFactor = 0.0; + private double queueSizeFactor = 0.0; private Optional endpointCertificateSecrets = Optional.empty(); private AthenzDomain athenzDomain; @@ -64,6 +66,16 @@ public class TestProperties implements ModelContext.Properties { @Override public Optional tlsSecrets() { return endpointCertificateSecrets.map(TlsSecrets::new); } @Override public double defaultTermwiseLimit() { return defaultTermwiseLimit; } + @Override + public double threadPoolSizeFactor() { + return threadPoolSizeFactor; + } + + @Override + public double queueSizeFactor() { + return queueSizeFactor; + } + @Override public double defaultSoftStartSeconds() { return softStartSeconds; @@ -86,7 +98,15 @@ public class TestProperties implements ModelContext.Properties { this.softStartSeconds = softStartSeconds; return this; } + public TestProperties setThreadPoolSizeFactor(double threadPoolSizeFactor) { + this.threadPoolSizeFactor = threadPoolSizeFactor; + return this; + } + public TestProperties setQueueSizeFactor(double queueSizeFactor) { + this.queueSizeFactor = queueSizeFactor; + return this; + } public TestProperties setApplicationId(ApplicationId applicationId) { this.applicationId = applicationId; return this; diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java index e59baf88422..29bb578a67b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ApplicationContainer.java @@ -5,6 +5,7 @@ import com.yahoo.config.model.api.container.ContainerServiceType; import com.yahoo.config.model.producer.AbstractConfigProducer; import com.yahoo.config.provision.Flavor; import com.yahoo.container.bundle.BundleInstantiationSpecification; +import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.osgi.provider.model.ComponentModel; import com.yahoo.prelude.fastsearch.FS4ResourcePool; import com.yahoo.search.config.QrStartConfig; @@ -15,7 +16,10 @@ import com.yahoo.vespa.model.container.component.Component; * * @author gjoranv */ -public final class ApplicationContainer extends Container implements QrStartConfig.Producer { +public final class ApplicationContainer extends Container implements + QrStartConfig.Producer, + ThreadpoolConfig.Producer +{ private static final String defaultHostedJVMArgs = "-XX:+UseOSErrorReporting -XX:+SuppressFatalErrorMessage"; @@ -73,4 +77,16 @@ public final class ApplicationContainer extends Container implements QrStartConf return (parent instanceof ContainerCluster) && (((ContainerCluster)parent).getDocproc() != null); } + @Override + public void getConfig(ThreadpoolConfig.Builder builder) { + if (! (parent instanceof ContainerCluster)) return; + if ((getHostResource() == null) || getHostResource().getFlavor().isEmpty()) return; + ContainerCluster containerCluster = (ContainerCluster) parent; + if (containerCluster.getThreadPoolSizeFactor() <= 0.0) return; + + NodeFlavorTuning flavorTuning = new NodeFlavorTuning(getHostResource().getFlavor().get()) + .setThreadPoolSizeFactor(containerCluster.getThreadPoolSizeFactor()) + .setQueueSizeFactor(containerCluster.getQueueSizeFactor()); + flavorTuning.getConfig(builder); + } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java index 833f6688fbc..b35b7562704 100755 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java @@ -160,12 +160,18 @@ public abstract class ContainerCluster private String jvmGCOptions = null; private String environmentVars = null; + private final double threadPoolSizeFactor; + private final double queueSizeFactor; + public ContainerCluster(AbstractConfigProducer parent, String subId, String name, DeployState deployState) { super(parent, subId); this.name = name; this.isHostedVespa = stateIsHosted(deployState); this.zone = (deployState != null) ? deployState.zone() : Zone.defaultZone(); + this.threadPoolSizeFactor = deployState.getProperties().threadPoolSizeFactor(); + this.queueSizeFactor = deployState.getProperties().queueSizeFactor(); + componentGroup = new ComponentGroup<>(this, "component"); addComponent(new StatisticsComponent()); @@ -186,6 +192,14 @@ public abstract class ContainerCluster addJaxProviders(); } + public double getThreadPoolSizeFactor() { + return threadPoolSizeFactor; + } + + public double getQueueSizeFactor() { + return queueSizeFactor; + } + public void setZone(Zone zone) { this.zone = zone; } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/NodeFlavorTuning.java b/config-model/src/main/java/com/yahoo/vespa/model/container/NodeFlavorTuning.java index 67938b36fd9..f9b50d0e641 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/NodeFlavorTuning.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/NodeFlavorTuning.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.container; import com.yahoo.config.provision.Flavor; +import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.search.config.QrStartConfig; /** @@ -9,10 +10,26 @@ import com.yahoo.search.config.QrStartConfig; * * @author balder */ -public class NodeFlavorTuning implements QrStartConfig.Producer { +public class NodeFlavorTuning implements + QrStartConfig.Producer, + ThreadpoolConfig.Producer +{ private final Flavor flavor; + public NodeFlavorTuning setThreadPoolSizeFactor(double threadPoolSizeFactor) { + this.threadPoolSizeFactor = threadPoolSizeFactor; + return this; + } + + public NodeFlavorTuning setQueueSizeFactor(double queueSizeFactor) { + this.queueSizeFactor = queueSizeFactor; + return this; + } + + private double threadPoolSizeFactor = 8.0; + private double queueSizeFactor = 8.0; + NodeFlavorTuning(Flavor flavor) { this.flavor = flavor; } @@ -22,4 +39,15 @@ public class NodeFlavorTuning implements QrStartConfig.Producer { builder.jvm.availableProcessors(Math.max(2, (int)Math.ceil(flavor.getMinCpuCores()))); } + @Override + public void getConfig(ThreadpoolConfig.Builder builder) { + // Controls max number of concurrent requests per container + int workerThreads = Math.max(2, (int)Math.ceil(flavor.getMinCpuCores() * threadPoolSizeFactor)); + builder.maxthreads(workerThreads); + + // This controls your burst handling capability. + // 0 => No extra burst handling beyond you max concurrent requests (maxthreads). + // N => N times max concurrent requests as a buffer for handling bursts + builder.queueSize((int)(workerThreads * queueSizeFactor)); + } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java index 33cf0635349..0f94df80421 100755 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/ContainerClusterTest.java @@ -9,9 +9,11 @@ import com.yahoo.config.model.deploy.DeployState; import com.yahoo.config.model.deploy.TestProperties; import com.yahoo.config.model.test.MockRoot; import com.yahoo.config.provision.Environment; +import com.yahoo.config.provision.Flavor; import com.yahoo.config.provision.RegionName; import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; +import com.yahoo.config.provisioning.FlavorsConfig; import com.yahoo.container.handler.ThreadpoolConfig; import com.yahoo.search.config.QrStartConfig; import com.yahoo.vespa.model.Host; @@ -164,6 +166,8 @@ public class ContainerClusterTest { cluster.getConfig(tpBuilder); ThreadpoolConfig threadpoolConfig = new ThreadpoolConfig(tpBuilder); assertEquals(10, threadpoolConfig.maxthreads()); + assertEquals(0, threadpoolConfig.queueSize()); + assertEquals(0, threadpoolConfig.softStartSeconds(), 0); } @Test @@ -213,9 +217,43 @@ public class ContainerClusterTest { cluster.getConfig(tpBuilder); ThreadpoolConfig threadpoolConfig = new ThreadpoolConfig(tpBuilder); assertEquals(500, threadpoolConfig.maxthreads()); + assertEquals(0, threadpoolConfig.queueSize()); assertEquals(300.0, threadpoolConfig.softStartSeconds(), 0.0); } + @Test + public void requireThatPoolAndQueueCanNotBeControlledByPropertiesWhenNoFlavor() { + DeployState state = new DeployState.Builder().properties(new TestProperties() + .setThreadPoolSizeFactor(8.5) + .setQueueSizeFactor(13.3)) + .build(); + MockRoot root = new MockRoot("foo", state); + ApplicationContainerCluster cluster = createContainerCluster(root, false); + addContainer(root.deployLogger(), cluster, "c1", "host-c1"); + + ThreadpoolConfig.Builder tpBuilder = new ThreadpoolConfig.Builder(); + cluster.getConfig(tpBuilder); + ThreadpoolConfig threadpoolConfig = new ThreadpoolConfig(tpBuilder); + assertEquals(500, threadpoolConfig.maxthreads()); + assertEquals(0, threadpoolConfig.queueSize()); + assertEquals(0.0, threadpoolConfig.softStartSeconds(), 0.0); + } + + @Test + public void requireThatPoolAndQueueCanBeControlledByPropertiesAndFlavor() { + FlavorsConfig.Flavor.Builder flavorBuilder = new FlavorsConfig.Flavor.Builder().name("my_flavor").minCpuCores(3); + NodeFlavorTuning nodeFlavorTuning = new NodeFlavorTuning(new Flavor(new FlavorsConfig.Flavor(flavorBuilder))) + .setThreadPoolSizeFactor(13.3) + .setQueueSizeFactor(17.5); + + ThreadpoolConfig.Builder tpBuilder = new ThreadpoolConfig.Builder(); + nodeFlavorTuning.getConfig(tpBuilder); + ThreadpoolConfig threadpoolConfig = new ThreadpoolConfig(tpBuilder); + assertEquals(40, threadpoolConfig.maxthreads()); + assertEquals(700, threadpoolConfig.queueSize()); + assertEquals(0.0, threadpoolConfig.softStartSeconds(), 0.0); + } + @Test public void requireThatDefaultThreadPoolConfigIsSane() { MockRoot root = new MockRoot("foo"); @@ -226,6 +264,7 @@ public class ContainerClusterTest { cluster.getConfig(tpBuilder); ThreadpoolConfig threadpoolConfig = new ThreadpoolConfig(tpBuilder); assertEquals(500, threadpoolConfig.maxthreads()); + assertEquals(0, threadpoolConfig.queueSize()); assertEquals(0.0, threadpoolConfig.softStartSeconds(), 0.0); } -- cgit v1.2.3