summaryrefslogtreecommitdiffstats
path: root/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java47
1 files changed, 7 insertions, 40 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
index 5bebd346bdb..29f53f0336d 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocationOptimizer.java
@@ -2,7 +2,6 @@
package com.yahoo.vespa.hosted.provision.autoscale;
import com.yahoo.config.provision.ClusterResources;
-import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
@@ -20,11 +19,6 @@ public class AllocationOptimizer {
private static final int minimumNodes = 2; // Since this number includes redundancy it cannot be lower than 2
private static final int maximumNodes = 150;
- // When a query is issued on a node the cost is the sum of a fixed cost component and a cost component
- // proportional to document count. We must account for this when comparing configurations with more or fewer nodes.
- // TODO: Measure this, and only take it into account with queries
- private static final double fixedCpuCostFraction = 0.1;
-
private final NodeRepository nodeRepository;
public AllocationOptimizer(NodeRepository nodeRepository) {
@@ -53,17 +47,10 @@ public class AllocationOptimizer {
for (int groups = limits.min().groups(); groups <= limits.max().groups(); groups++) {
for (int nodes = limits.min().nodes(); nodes <= limits.max().nodes(); nodes++) {
if (nodes % groups != 0) continue;
- int groupSize = nodes / groups;
-
- // Adjust for redundancy: Node in group if groups = 1, an extra group if multiple groups
- // TODO: Make the best choice based on size and redundancy setting instead
- int nodesAdjustedForRedundancy = target.adjustForRedundancy() && nodes > 1 ? (groups == 1 ? nodes - 1 : nodes - groupSize) : nodes;
- int groupsAdjustedForRedundancy = target.adjustForRedundancy() && nodes > 1 ? (groups == 1 ? 1 : groups - 1) : groups;
ClusterResources next = new ClusterResources(nodes,
groups,
- nodeResourcesWith(nodesAdjustedForRedundancy,
- groupsAdjustedForRedundancy,
+ nodeResourcesWith(nodes, groups,
limits, target, current, clusterModel));
var allocatableResources = AllocatableClusterResources.from(next, current.clusterSpec(), limits,
hosts, nodeRepository);
@@ -85,34 +72,14 @@ public class AllocationOptimizer {
ResourceTarget target,
AllocatableClusterResources current,
ClusterModel clusterModel) {
- double cpu, memory, disk;
- int groupSize = nodes / groups;
-
- if (current.clusterSpec().type() == ClusterSpec.Type.content) { // load scales with node share of content
- // Cpu: Query cpu scales with cluster size, write cpu scales with group size
- // Memory and disk: Scales with group size
-
- // The fixed cost portion of cpu does not scale with changes to the node count
- double queryCpuPerGroup = fixedCpuCostFraction * target.resources().vcpu() +
- (1 - fixedCpuCostFraction) * target.resources().vcpu() * current.groupSize() / groupSize;
-
- double queryCpu = queryCpuPerGroup * current.groups() / groups;
- double writeCpu = target.resources().vcpu() * current.groupSize() / groupSize;
- cpu = clusterModel.queryCpuFraction() * queryCpu + (1 - clusterModel.queryCpuFraction()) * writeCpu;
- memory = target.resources().memoryGb() * current.groupSize() / groupSize;
- disk = target.resources().diskGb() * current.groupSize() / groupSize;
- }
- else {
- cpu = target.resources().vcpu() * current.nodes() / nodes;
- memory = target.resources().memoryGb();
- disk = target.resources().diskGb();
- }
+ var scaled = clusterModel.loadWith(nodes, groups)
+ .scaled(Load.one().divide(clusterModel.redundancyAdjustment()).scaled(target.resources()));
// Combine the scaled resource values computed here
// with the currently configured non-scaled values, given in the limits, if any
- NodeResources nonScaled = limits.isEmpty() || limits.min().nodeResources().isUnspecified()
- ? current.advertisedResources().nodeResources()
- : limits.min().nodeResources(); // min=max for non-scaled
- return nonScaled.withVcpu(cpu).withMemoryGb(memory).withDiskGb(disk);
+ var nonScaled = limits.isEmpty() || limits.min().nodeResources().isUnspecified()
+ ? current.advertisedResources().nodeResources()
+ : limits.min().nodeResources(); // min=max for non-scaled
+ return nonScaled.withVcpu(scaled.vcpu()).withMemoryGb(scaled.memoryGb()).withDiskGb(scaled.diskGb());
}
/** Returns a copy of the given limits where the minimum nodes are at least the given value when allowed */