aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
diff options
context:
space:
mode:
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java')
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java30
1 files changed, 23 insertions, 7 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
index 0facc6d37ea..1928a784763 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java
@@ -57,6 +57,7 @@ public class ClusterModel {
// Lazily initialized members
private Double queryFractionOfMax = null;
private Double maxQueryGrowthRate = null;
+ private OptionalDouble averageQueryRate = null;
public ClusterModel(Zone zone,
Application application,
@@ -131,19 +132,25 @@ public class ClusterModel {
/**
* Returns the predicted max query growth rate per minute as a fraction of the average traffic
- * in the scaling window
+ * in the scaling window.
*/
public double maxQueryGrowthRate() {
if (maxQueryGrowthRate != null) return maxQueryGrowthRate;
return maxQueryGrowthRate = clusterTimeseries().maxQueryGrowthRate(scalingDuration(), clock);
}
- /** Returns the average query rate in the scaling window as a fraction of the max observed query rate */
+ /** Returns the average query rate in the scaling window as a fraction of the max observed query rate. */
public double queryFractionOfMax() {
if (queryFractionOfMax != null) return queryFractionOfMax;
return queryFractionOfMax = clusterTimeseries().queryFractionOfMax(scalingDuration(), clock);
}
+ /** Returns the average query rate in the scaling window. */
+ public OptionalDouble averageQueryRate() {
+ if (averageQueryRate != null) return averageQueryRate;
+ return averageQueryRate = clusterTimeseries().queryRate(scalingDuration(), clock);
+ }
+
/** Returns the average of the last load measurement from each node. */
public Load currentLoad() { return nodeTimeseries().currentLoad(); }
@@ -239,7 +246,8 @@ public class ClusterModel {
// Cap headroom at 10% above the historical observed peak
if (queryFractionOfMax() != 0)
growthRateHeadroom = Math.min(growthRateHeadroom, 1 / queryFractionOfMax() + 0.1);
- return growthRateHeadroom;
+
+ return adjustByConfidence(growthRateHeadroom);
}
/**
@@ -255,15 +263,23 @@ public class ClusterModel {
trafficShiftHeadroom = 1/application.status().maxReadShare();
else
trafficShiftHeadroom = application.status().maxReadShare() / application.status().currentReadShare();
- return Math.min(trafficShiftHeadroom, 1/application.status().maxReadShare());
+ return adjustByConfidence(Math.min(trafficShiftHeadroom, 1/application.status().maxReadShare()));
+ }
+
+ /**
+ * Headroom values are a multiplier of the current query rate.
+ * Adjust this value closer to 1 if the query rate is too low to derive statistical conclusions
+ * with high confidence to avoid large adjustments caused by random noise due to low traffic numbers.
+ */
+ private double adjustByConfidence(double headroom) {
+ return ( (headroom -1 ) * Math.min(1, averageQueryRate().orElse(0) / 100.0) ) + 1;
}
/** The estimated fraction of cpu usage which goes to processing queries vs. writes */
public double queryCpuFraction() {
- OptionalDouble queryRate = clusterTimeseries().queryRate(scalingDuration(), clock);
OptionalDouble writeRate = clusterTimeseries().writeRate(scalingDuration(), clock);
- if (queryRate.orElse(0) == 0 && writeRate.orElse(0) == 0) return queryCpuFraction(0.5);
- return queryCpuFraction(queryRate.orElse(0) / (queryRate.orElse(0) + writeRate.orElse(0)));
+ if (averageQueryRate().orElse(0) == 0 && writeRate.orElse(0) == 0) return queryCpuFraction(0.5);
+ return queryCpuFraction(averageQueryRate().orElse(0) / (averageQueryRate().orElse(0) + writeRate.orElse(0)));
}
private double queryCpuFraction(double queryRateFraction) {