summaryrefslogtreecommitdiffstats
path: root/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java')
-rw-r--r--container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java107
1 files changed, 79 insertions, 28 deletions
diff --git a/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java b/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
index c9981b3598b..ddf4fae5cba 100644
--- a/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
+++ b/container-search/src/test/java/com/yahoo/search/dispatch/LoadBalancerTest.java
@@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;
import java.time.Duration;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -26,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
* @author ollivir
*/
public class LoadBalancerTest {
-
+ private static final double delta = 0.0000001;
@Test
void requireThatLoadBalancerServesSingleNodeSetups() {
Node n1 = new Node(0, "test-node1", 0);
@@ -34,7 +35,7 @@ public class LoadBalancerTest {
LoadBalancer lb = new LoadBalancer(cluster, LoadBalancer.Policy.ROUNDROBIN);
Optional<Group> grp = lb.takeGroup(null);
- Group group = grp.orElseGet(() -> {
+ Group group = grp.orElseThrow(() -> {
throw new AssertionFailedError("Expected a SearchCluster.Group");
});
assertEquals(1, group.nodes().size());
@@ -48,7 +49,7 @@ public class LoadBalancerTest {
LoadBalancer lb = new LoadBalancer(cluster, LoadBalancer.Policy.ROUNDROBIN);
Optional<Group> grp = lb.takeGroup(null);
- Group group = grp.orElseGet(() -> {
+ Group group = grp.orElseThrow(() -> {
throw new AssertionFailedError("Expected a SearchCluster.Group");
});
assertEquals(1, group.nodes().size());
@@ -79,7 +80,7 @@ public class LoadBalancerTest {
Group group = grp.get();
int id1 = group.id();
// release allocation
- lb.releaseGroup(group, true, Duration.ofMillis(1));
+ lb.releaseGroup(group, true, RequestDuration.of(Duration.ofMillis(1)));
// get second group
grp = lb.takeGroup(null);
@@ -89,31 +90,30 @@ public class LoadBalancerTest {
@Test
void requireCorrectAverageSearchTimeDecay() {
- final double delta = 0.00001;
-
+ AdaptiveScheduler.DecayByRequests decayer = new AdaptiveScheduler.DecayByRequests(0, Duration.ofSeconds(1));
GroupStatus gs = newGroupStatus(1);
- gs.setQueryStatistics(0, Duration.ofSeconds(1));
- updateSearchTime(gs, Duration.ofSeconds(1));
- assertEquals(Duration.ofSeconds(1), gs.averageSearchTime());
- updateSearchTime(gs, Duration.ofSeconds(2));
- assertEquals(Duration.ofNanos(1023255813), gs.averageSearchTime());
- updateSearchTime(gs, Duration.ofSeconds(2));
- assertEquals(Duration.ofNanos(1045454545), gs.averageSearchTime());
- updateSearchTime(gs, Duration.ofMillis(100));
- updateSearchTime(gs, Duration.ofMillis(100));
- updateSearchTime(gs, Duration.ofMillis(100));
- updateSearchTime(gs, Duration.ofMillis(100));
- assertEquals(Duration.ofNanos(966666666), gs.averageSearchTime());
+ gs.setDecayer(decayer);
+ updateSearchTime(gs, RequestDuration.of(Duration.ofSeconds(1)));
+ assertEquals(Duration.ofSeconds(1), decayer.averageSearchTime());
+ updateSearchTime(gs, RequestDuration.of(Duration.ofSeconds(2)));
+ assertEquals(Duration.ofNanos(1023255813), decayer.averageSearchTime());
+ updateSearchTime(gs, RequestDuration.of(Duration.ofSeconds(2)));
+ assertEquals(Duration.ofNanos(1045454545), decayer.averageSearchTime());
+ updateSearchTime(gs, RequestDuration.of(Duration.ofMillis(100)));
+ updateSearchTime(gs, RequestDuration.of(Duration.ofMillis(100)));
+ updateSearchTime(gs, RequestDuration.of(Duration.ofMillis(100)));
+ updateSearchTime(gs, RequestDuration.of(Duration.ofMillis(100)));
+ assertEquals(Duration.ofNanos(966666666), decayer.averageSearchTime());
for (int i = 0; i < 10000; i++) {
- updateSearchTime(gs, Duration.ofSeconds(1));
+ updateSearchTime(gs, RequestDuration.of(Duration.ofSeconds(1)));
}
- assertEquals(Duration.ofNanos(999999812), gs.averageSearchTime());
- updateSearchTime(gs, Duration.ofMillis(100));
- assertEquals(Duration.ofNanos(999099812), gs.averageSearchTime());
+ assertEquals(Duration.ofNanos(999999812), decayer.averageSearchTime());
+ updateSearchTime(gs, RequestDuration.of(Duration.ofMillis(100)));
+ assertEquals(Duration.ofNanos(999099812), decayer.averageSearchTime());
for (int i = 0; i < 10000; i++) {
- updateSearchTime(gs, Duration.ZERO);
+ updateSearchTime(gs, RequestDuration.of(Duration.ZERO));
}
- assertEquals(Duration.ofNanos(1045087), gs.averageSearchTime());
+ assertEquals(Duration.ofNanos(1045087), decayer.averageSearchTime());
}
@Test
@@ -123,7 +123,7 @@ public class LoadBalancerTest {
scoreboard.add(newGroupStatus(i));
}
Random seq = sequence(0.0, 0.1, 0.2, 0.39, 0.4, 0.6, 0.8, 0.99999);
- AdaptiveScheduler sched = new AdaptiveScheduler(seq, scoreboard);
+ AdaptiveScheduler sched = new AdaptiveScheduler(AdaptiveScheduler.Type.REQUESTS, seq, scoreboard);
assertEquals(0, sched.takeNextGroup(null).get().groupId());
assertEquals(0, sched.takeNextGroup(null).get().groupId());
@@ -140,11 +140,15 @@ public class LoadBalancerTest {
List<GroupStatus> scoreboard = new ArrayList<>();
for (int i = 0; i < 5; i++) {
GroupStatus gs = newGroupStatus(i);
- gs.setQueryStatistics(1, Duration.ofMillis((long)(0.1 * (i + 1)*1000.0)));
scoreboard.add(gs);
}
Random seq = sequence(0.0, 0.4379, 0.4380, 0.6569, 0.6570, 0.8029, 0.8030, 0.9124, 0.9125);
- AdaptiveScheduler sched = new AdaptiveScheduler(seq, scoreboard);
+ AdaptiveScheduler sched = new AdaptiveScheduler(AdaptiveScheduler.Type.REQUESTS, seq, scoreboard);
+ int i= 0;
+ for (GroupStatus gs : scoreboard) {
+ gs.setDecayer(new AdaptiveScheduler.DecayByRequests(1, Duration.ofMillis((long)(0.1 * (i + 1)*1000.0))));
+ i++;
+ }
assertEquals(0, sched.takeNextGroup(null).get().groupId());
assertEquals(0, sched.takeNextGroup(null).get().groupId());
@@ -190,7 +194,54 @@ public class LoadBalancerTest {
assertEquals(0, allocate(sched.takeNextGroup(null).get()).groupId());
}
- private static void updateSearchTime(GroupStatus gs, Duration time) {
+ private static int countRequestsToReach90p(Duration timeBetweenSample, Duration searchTime) {
+ double p90 = 0.9*searchTime.toMillis()/1000.0;
+ GroupStatus.Decayer decayer = new AdaptiveScheduler.DecayByTime(Duration.ofMillis(1), RequestDuration.of(Instant.EPOCH, Duration.ZERO));
+ int requests = 0;
+ Instant start = Instant.EPOCH;
+ while (decayer.averageCost() < p90) {
+ decayer.decay(RequestDuration.of(start, searchTime));
+ start = start.plus(timeBetweenSample);
+ requests++;
+ }
+ return requests;
+ }
+
+ @Test
+ public void requireDecayByTimeToDependOnlyOnTime() {
+ GroupStatus.Decayer decayer = new AdaptiveScheduler.DecayByTime(Duration.ofMillis(2), RequestDuration.of(Instant.EPOCH, Duration.ZERO));
+ assertEquals(0.002, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(1000), Duration.ofMillis(10)));
+ assertEquals(0.003616, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(2000), Duration.ofMillis(10)));
+ assertEquals(0.0048928, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(3000), Duration.ofMillis(10)));
+ assertEquals(0.00591424, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(3100), Duration.ofMillis(10)));
+ assertEquals(0.0059959552, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(3100), Duration.ofMillis(10)));
+ assertEquals(0.0059959552, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(3000), Duration.ofMillis(10)));
+ assertEquals(0.006076036096, decayer.averageCost(), delta);
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(5000), Duration.ofMillis(10)));
+ assertEquals(0.0076456216576000005, decayer.averageCost(), delta);
+ assertEquals(110, countRequestsToReach90p(Duration.ofMillis(100), Duration.ofMillis(10)));
+ assertEquals(55, countRequestsToReach90p(Duration.ofMillis(200), Duration.ofMillis(10)));
+ assertEquals(11, countRequestsToReach90p(Duration.ofMillis(1000), Duration.ofMillis(10)));
+ }
+
+ @Test
+ public void requireDecayByTimeToNotJumpTooFar() {
+ AdaptiveScheduler.DecayByTime decayer = new AdaptiveScheduler.DecayByTime(Duration.ofMillis(2), RequestDuration.of(Instant.EPOCH, Duration.ZERO));
+ assertEquals(0.002, decayer.averageCost(), delta);
+ assertEquals(Duration.ofMillis(2), decayer.averageSearchTime());
+ decayer.decay(RequestDuration.of(Instant.ofEpochMilli(10000), Duration.ofMillis(10)));
+ assertEquals(0.006, decayer.averageCost(), delta); // Capped at 50% sampleWeight
+ assertEquals(Duration.ofMillis(6), decayer.averageSearchTime());
+
+ }
+
+ private static void updateSearchTime(GroupStatus gs, RequestDuration time) {
gs.allocate();
gs.release(true, time);
}