From 7ba2097fe1792ad15658c78059ff08deca01f621 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Wed, 3 Aug 2022 17:40:08 +0200 Subject: Eliminate ResourceTarget --- .../provision/autoscale/AllocationOptimizer.java | 6 +-- .../hosted/provision/autoscale/Autoscaler.java | 2 +- .../hosted/provision/autoscale/ResourceTarget.java | 46 ---------------------- .../provisioning/NodeRepositoryProvisioner.java | 3 +- 4 files changed, 5 insertions(+), 52 deletions(-) delete mode 100644 node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java 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 29f53f0336d..84ecaa3453d 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 @@ -32,7 +32,7 @@ public class AllocationOptimizer { * @return the best allocation, if there are any possible legal allocations, fulfilling the target * fully or partially, within the limits */ - public Optional findBestAllocation(ResourceTarget target, + public Optional findBestAllocation(NodeResources target, AllocatableClusterResources current, ClusterModel clusterModel, Limits limits) { @@ -69,11 +69,11 @@ public class AllocationOptimizer { private NodeResources nodeResourcesWith(int nodes, int groups, Limits limits, - ResourceTarget target, + NodeResources target, AllocatableClusterResources current, ClusterModel clusterModel) { var scaled = clusterModel.loadWith(nodes, groups) - .scaled(Load.one().divide(clusterModel.redundancyAdjustment()).scaled(target.resources())); + .scaled(Load.one().divide(clusterModel.redundancyAdjustment()).scaled(target)); // Combine the scaled resource values computed here // with the currently configured non-scaled values, given in the limits, if any var nonScaled = limits.isEmpty() || limits.min().nodeResources().isUnspecified() diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java index ac072639cfe..0931fc6af3b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java @@ -89,7 +89,7 @@ public class Autoscaler { " nodes, but require from " + clusterNodes.size()); var currentAllocation = new AllocatableClusterResources(clusterNodes.asList(), nodeRepository); - var target = ResourceTarget.idealLoad(clusterModel, currentAllocation); + var target = clusterModel.loadAdjustment().scaled(currentAllocation.realResources().nodeResources()); Optional bestAllocation = allocationOptimizer.findBestAllocation(target, currentAllocation, clusterModel, limits); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java deleted file mode 100644 index 7bc019caabb..00000000000 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ResourceTarget.java +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.vespa.hosted.provision.autoscale; - -import com.yahoo.config.provision.NodeResources; -import com.yahoo.vespa.hosted.provision.applications.Application; - -import java.time.Clock; -import java.time.Duration; -import java.util.OptionalDouble; - -/** - * A resource target to hit for the allocation optimizer. - * The target is measured in cpu, memory and disk per node in the current allocation. - * - * @author bratseth - */ -public class ResourceTarget { - - /** The target real resources per node, assuming the node assignment where this was decided */ - private final NodeResources resources; - - private ResourceTarget(NodeResources resources) { - this.resources = resources; - } - - /** Returns the target resources per node in terms of the current allocation */ - public NodeResources resources() { return resources; } - - @Override - public String toString() { - return "target " + resources; - } - - /** Create a target of achieving ideal load given a current load */ - public static ResourceTarget idealLoad(ClusterModel clusterModel, - AllocatableClusterResources current) { - return new ResourceTarget(clusterModel.loadAdjustment().scaled(current.realResources().nodeResources())); - } - - /** Crete a target of preserving a current allocation */ - public static ResourceTarget preserve(ClusterModel clusterModel, - AllocatableClusterResources current) { - return new ResourceTarget(current.realResources().nodeResources()); - } - -} diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 8e00a623e1c..0ce84559d1a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -27,7 +27,6 @@ import com.yahoo.vespa.hosted.provision.autoscale.AllocatableClusterResources; import com.yahoo.vespa.hosted.provision.autoscale.AllocationOptimizer; import com.yahoo.vespa.hosted.provision.autoscale.ClusterModel; import com.yahoo.vespa.hosted.provision.autoscale.Limits; -import com.yahoo.vespa.hosted.provision.autoscale.ResourceTarget; import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.node.filter.ApplicationFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeHostFilter; @@ -196,7 +195,7 @@ public class NodeRepositoryProvisioner implements Provisioner { if (! firstDeployment && currentAsAdvertised.isWithin(limits.min(), limits.max())) return currentAsAdvertised; // Otherwise, find an allocation that preserves the current resources as well as possible - return allocationOptimizer.findBestAllocation(ResourceTarget.preserve(clusterModel, current), + return allocationOptimizer.findBestAllocation(current.realResources().nodeResources(), current, clusterModel, limits) -- cgit v1.2.3 From ec4f38324106df044656b4a74fc681d12937f7e3 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Wed, 3 Aug 2022 17:54:43 +0200 Subject: Scale load as late as possible --- .../hosted/provision/autoscale/AllocationOptimizer.java | 17 ++++++++++------- .../vespa/hosted/provision/autoscale/Autoscaler.java | 4 +--- .../provisioning/NodeRepositoryProvisioner.java | 3 ++- 3 files changed, 13 insertions(+), 11 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 84ecaa3453d..2befd69f893 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 @@ -26,13 +26,13 @@ public class AllocationOptimizer { } /** - * Searches the space of possible allocations given a target + * Searches the space of possible allocations given a target relative load * and (optionally) cluster limits and returns the best alternative. * * @return the best allocation, if there are any possible legal allocations, fulfilling the target * fully or partially, within the limits */ - public Optional findBestAllocation(NodeResources target, + public Optional findBestAllocation(Load targetLoad, AllocatableClusterResources current, ClusterModel clusterModel, Limits limits) { @@ -51,7 +51,7 @@ public class AllocationOptimizer { ClusterResources next = new ClusterResources(nodes, groups, nodeResourcesWith(nodes, groups, - limits, target, current, clusterModel)); + limits, targetLoad, current, clusterModel)); var allocatableResources = AllocatableClusterResources.from(next, current.clusterSpec(), limits, hosts, nodeRepository); if (allocatableResources.isEmpty()) continue; @@ -64,16 +64,19 @@ public class AllocationOptimizer { /** * For the observed load this instance is initialized with, returns the resources needed per node to be at - * ideal load given a target node count + * the target relative load, given a target node and group count. */ private NodeResources nodeResourcesWith(int nodes, int groups, Limits limits, - NodeResources target, + Load targetLoad, AllocatableClusterResources current, ClusterModel clusterModel) { - var scaled = clusterModel.loadWith(nodes, groups) - .scaled(Load.one().divide(clusterModel.redundancyAdjustment()).scaled(target)); + var scaled = targetLoad // redundancy aware target relative to current load + .multiply(clusterModel.loadWith(nodes, groups)) // redundancy aware adjustment with these counts + .divide(clusterModel.redundancyAdjustment()) // correct for double redundancy adjustment + .scaled(current.realResources().nodeResources()); + // Combine the scaled resource values computed here // with the currently configured non-scaled values, given in the limits, if any var nonScaled = limits.isEmpty() || limits.min().nodeResources().isUnspecified() diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java index 0931fc6af3b..7a02fa9eb7e 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java @@ -89,10 +89,8 @@ public class Autoscaler { " nodes, but require from " + clusterNodes.size()); var currentAllocation = new AllocatableClusterResources(clusterNodes.asList(), nodeRepository); - var target = clusterModel.loadAdjustment().scaled(currentAllocation.realResources().nodeResources()); - Optional bestAllocation = - allocationOptimizer.findBestAllocation(target, currentAllocation, clusterModel, limits); + allocationOptimizer.findBestAllocation(clusterModel.loadAdjustment(), currentAllocation, clusterModel, limits); if (bestAllocation.isEmpty()) return Advice.dontScale(Status.insufficient, "No allocations are possible within configured limits"); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 0ce84559d1a..065293ca5d8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -27,6 +27,7 @@ import com.yahoo.vespa.hosted.provision.autoscale.AllocatableClusterResources; import com.yahoo.vespa.hosted.provision.autoscale.AllocationOptimizer; import com.yahoo.vespa.hosted.provision.autoscale.ClusterModel; import com.yahoo.vespa.hosted.provision.autoscale.Limits; +import com.yahoo.vespa.hosted.provision.autoscale.Load; import com.yahoo.vespa.hosted.provision.node.Allocation; import com.yahoo.vespa.hosted.provision.node.filter.ApplicationFilter; import com.yahoo.vespa.hosted.provision.node.filter.NodeHostFilter; @@ -195,7 +196,7 @@ public class NodeRepositoryProvisioner implements Provisioner { if (! firstDeployment && currentAsAdvertised.isWithin(limits.min(), limits.max())) return currentAsAdvertised; // Otherwise, find an allocation that preserves the current resources as well as possible - return allocationOptimizer.findBestAllocation(current.realResources().nodeResources(), + return allocationOptimizer.findBestAllocation(Load.one(), current, clusterModel, limits) -- cgit v1.2.3