diff options
author | Valerij Fredriksen <freva@users.noreply.github.com> | 2022-08-01 22:42:58 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-01 22:42:58 +0200 |
commit | ccd2818a152e44396f15cb399fe851f10c350368 (patch) | |
tree | f6983a2ec97709104e6b0d1adc05387b06d6ca28 /node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java | |
parent | 9719904260e487af585b0f55facaf48839ac9ee9 (diff) | |
parent | 3a80c6d45b5a700894cacc9e26967f3273dbcddd (diff) |
Merge pull request #23561 from vespa-engine/bratseth/test-cleanup-2v8.27.12
Bratseth/test cleanup 2
Diffstat (limited to 'node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java')
-rw-r--r-- | node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java new file mode 100644 index 00000000000..db4fe917b53 --- /dev/null +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/Loader.java @@ -0,0 +1,158 @@ +// 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.collections.Pair; +import com.yahoo.vespa.hosted.provision.Node; +import com.yahoo.vespa.hosted.provision.NodeList; + +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.function.IntFunction; + +/** + * A helper for applying load to an application represented by a fixture, + * + * @author bratseth + */ +public class Loader { + + private final Fixture fixture; + + public Loader(Fixture fixture) { + this.fixture = fixture; + } + + /** + * Adds measurements with the given resource value and ideal values for the other resources, + * scaled to take one node redundancy into account. + * (I.e we adjust to measure a bit lower load than "naively" wanted to offset for the autoscaler + * wanting to see the ideal load with one node missing.) + * + * @param count the number of measurements + */ + public Duration addCpuMeasurements(double value, int count) { + NodeList nodes = fixture.nodes(); + float oneExtraNodeFactor = (float)(nodes.size() - 1.0) / (nodes.size()); + Instant initialTime = fixture.tester().clock().instant(); + for (int i = 0; i < count; i++) { + fixture.tester().clock().advance(Duration.ofSeconds(150)); + for (Node node : nodes) { + Load load = new Load(value, + ClusterModel.idealMemoryLoad, + ClusterModel.idealContentDiskLoad).multiply(oneExtraNodeFactor); + fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), + new NodeMetricSnapshot(fixture.tester().clock().instant(), + load, + 0, + true, + true, + 0.0)))); + } + } + return Duration.between(initialTime, fixture.tester().clock().instant()); + } + + /** Creates the given number of measurements, spaced 5 minutes between, using the given function */ + public Duration addLoadMeasurements(int measurements, IntFunction<Double> queryRate, IntFunction<Double> writeRate) { + Instant initialTime = fixture.tester().clock().instant(); + for (int i = 0; i < measurements; i++) { + fixture.tester().nodeMetricsDb().addClusterMetrics(fixture.applicationId(), + Map.of(fixture.clusterId(), new ClusterMetricSnapshot(fixture.tester().clock().instant(), + queryRate.apply(i), + writeRate.apply(i)))); + fixture.tester().clock().advance(Duration.ofMinutes(5)); + } + return Duration.between(initialTime, fixture.tester().clock().instant()); + } + + public void applyCpuLoad(double cpuLoad, int measurements) { + Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements + addCpuMeasurements((float)cpuLoad, measurements); + fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); + addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + } + + public void applyMemLoad(double memLoad, int measurements) { + Duration samplingInterval = Duration.ofSeconds(150L); // in addMemMeasurements + addMemMeasurements(memLoad, measurements); + fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); + addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + } + + /** + * Adds measurements with the given resource value and ideal values for the other resources, + * scaled to take one node redundancy into account. + * (I.e we adjust to measure a bit lower load than "naively" wanted to offset for the autoscaler + * wanting to see the ideal load with one node missing.) + */ + public void addMemMeasurements(double value, int count) { + NodeList nodes = fixture.nodes(); + float oneExtraNodeFactor = (float)(nodes.size() - 1.0) / (nodes.size()); + for (int i = 0; i < count; i++) { + fixture.tester().clock().advance(Duration.ofMinutes(1)); + for (Node node : nodes) { + Load load = new Load(0.2, + value, + ClusterModel.idealContentDiskLoad).multiply(oneExtraNodeFactor); + fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), + new NodeMetricSnapshot(fixture.tester().clock().instant(), + load, + 0, + true, + true, + 0.0)))); + } + } + } + + public Duration addMeasurements(double cpu, double memory, double disk, int count) { + return addMeasurements(cpu, memory, disk, 0, true, true, count); + } + + public Duration addMeasurements(double cpu, double memory, double disk, int generation, boolean inService, boolean stable, + int count) { + Instant initialTime = fixture.tester().clock().instant(); + for (int i = 0; i < count; i++) { + fixture.tester().clock().advance(Duration.ofMinutes(1)); + for (Node node : fixture.nodes()) { + fixture.tester().nodeMetricsDb().addNodeMetrics(List.of(new Pair<>(node.hostname(), + new NodeMetricSnapshot(fixture.tester().clock().instant(), + new Load(cpu, memory, disk), + generation, + inService, + stable, + 0.0)))); + } + } + return Duration.between(initialTime, fixture.tester().clock().instant()); + } + + public void applyLoad(double cpuLoad, double memoryLoad, double diskLoad, int measurements) { + Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements + addMeasurements(cpuLoad, memoryLoad, diskLoad, measurements); + fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); + addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + } + + public void applyLoad(double cpuLoad, double memoryLoad, double diskLoad, int generation, boolean inService, boolean stable, int measurements) { + Duration samplingInterval = Duration.ofSeconds(150L); // in addCpuMeasurements + addMeasurements(cpuLoad, memoryLoad, diskLoad, generation, inService, stable, measurements); + fixture.tester().clock().advance(samplingInterval.negated().multipliedBy(measurements)); + addQueryRateMeasurements(measurements, samplingInterval, t -> t == 0 ? 20.0 : 10.0); // Query traffic only + } + + public Duration addQueryRateMeasurements(int measurements, Duration samplingInterval, IntFunction<Double> queryRate) { + Instant initialTime = fixture.tester().clock().instant(); + for (int i = 0; i < measurements; i++) { + fixture.tester().nodeMetricsDb().addClusterMetrics(fixture.applicationId(), + Map.of(fixture.clusterId(), new ClusterMetricSnapshot(fixture.tester().clock().instant(), + queryRate.apply(i), + 0.0))); + fixture.tester().clock().advance(samplingInterval); + } + return Duration.between(initialTime, fixture.tester().clock().instant()); + } + +} |