aboutsummaryrefslogtreecommitdiffstats
path: root/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterTimeseriesTest.java
blob: 8c40d3d2be265fb803336b01dd923ba5fd145f0c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright Vespa.ai. 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.ClusterSpec;
import com.yahoo.test.ManualClock;
import org.junit.Test;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.function.IntFunction;

import static org.junit.Assert.assertEquals;

/**
 * @author bratseth
 */
public class ClusterTimeseriesTest {

    private static final double delta = 0.001;
    private static final ClusterSpec.Id cluster = new ClusterSpec.Id("test");

    @Test
    public void test_empty() {
        ManualClock clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, List.of());
        assertEquals(0.1, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_constant_rate_short() {
        var clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, queryRate(10, clock, t -> 50.0));
        assertEquals(0.1, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_constant_rate_long() {
        var clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, queryRate(10000, clock, t -> 50.0));
        assertEquals(0.0, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_single_spike() {
        var clock = new ManualClock();
        var snapshots = new ArrayList<ClusterMetricSnapshot>();
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        snapshots.addAll(queryRate(10, clock, t -> 400.0));
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        assertEquals((400-50)/5.0/50.0, new ClusterTimeseries(cluster, snapshots).maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_three_spikes() {
        var clock = new ManualClock();
        var snapshots = new ArrayList<ClusterMetricSnapshot>();
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        snapshots.addAll(queryRate(10, clock, t -> 400.0));
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        snapshots.addAll(queryRate(10, clock, t -> 600.0));
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        snapshots.addAll(queryRate(10, clock, t -> 800.0));
        snapshots.addAll(queryRate(1000, clock, t ->  50.0));
        assertEquals((800-50)/5.0/50.0, new ClusterTimeseries(cluster, snapshots).maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_single_hill() {
        var clock = new ManualClock();
        var snapshots = new ArrayList<ClusterMetricSnapshot>();
        snapshots.addAll(queryRate(100, clock, t ->  (double)t));
        snapshots.addAll(queryRate(100, clock, t -> 100.0 - t));
        assertEquals(1/5.0, new ClusterTimeseries(cluster, snapshots).maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_smooth_curve() {
        var clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, queryRate(10000, clock,
                                                             t -> 10.0 + 100.0 * Math.sin(t)));
        assertEquals(0.26, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_smooth_curve_small_variation() {
        var clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, queryRate(10000, clock,
                                                                           t -> 1000.0 + 10.0 * Math.sin(t)));
        assertEquals(0.0, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    @Test
    public void test_two_periods() {
        var clock = new ManualClock();
        var timeseries = new ClusterTimeseries(cluster, queryRate(10000, clock,
                                                             t -> 10.0 + 100.0 * Math.sin(t) + 80.0 * Math.sin(10 * t)) );
        assertEquals(1.765, timeseries.maxQueryGrowthRate(Duration.ofMinutes(5), clock), delta);
    }

    private List<ClusterMetricSnapshot> queryRate(int count, ManualClock clock, IntFunction<Double> rate) {
        List<ClusterMetricSnapshot> snapshots = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            snapshots.add(new ClusterMetricSnapshot(clock.instant(), rate.apply(i), 0.0));
            clock.advance(Duration.ofMinutes(5));
        }
        return snapshots;
    }

}