@Override public ListenableFuture<?> processFor(Duration duration) { started.set(true); ticker.increment(quantaTimeMillis, MILLISECONDS); globalPhaser.arriveAndAwaitAdvance(); int phase = beginQuantaPhaser.arriveAndAwaitAdvance(); firstPhase.compareAndSet(-1, phase - 1); lastPhase.set(phase); endQuantaPhaser.arriveAndAwaitAdvance(); if (completedPhases.incrementAndGet() >= requiredPhases) { endQuantaPhaser.arriveAndDeregister(); beginQuantaPhaser.arriveAndDeregister(); globalPhaser.arriveAndDeregister(); completed.set(null); } return Futures.immediateFuture(null); }
@Test public void testFailureInterval() { TestingTicker ticker = new TestingTicker(); ticker.increment(1, NANOSECONDS); Backoff backoff = new Backoff(1, new Duration(15, SECONDS), ticker, ImmutableList.of(new Duration(10, MILLISECONDS))); ticker.increment(10, MICROSECONDS); // verify initial state assertEquals(backoff.getFailureCount(), 0); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 0); // first failure, should never fail assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 0); ticker.increment(14, SECONDS); // second failure within the limit, should not fail assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 14); ticker.increment(1, SECONDS); // final failure after the limit causes failure assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 3); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 15); }
@Test public void testStartRequest() { TestingTicker ticker = new TestingTicker(); ticker.increment(1, NANOSECONDS); Backoff backoff = new Backoff(1, new Duration(15, SECONDS), ticker, ImmutableList.of(new Duration(10, MILLISECONDS))); ticker.increment(10, MICROSECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 0); assertEquals(backoff.getFailureRequestTimeTotal().roundTo(SECONDS), 0); ticker.increment(7, SECONDS); backoff.startRequest(); ticker.increment(7, SECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 14); // failed request took 7 seconds. assertEquals(backoff.getFailureRequestTimeTotal().roundTo(SECONDS), 7); ticker.increment(1, SECONDS); backoff.startRequest(); ticker.increment(1, SECONDS); assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 3); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 16); // failed requests took 7+1 seconds. assertEquals(backoff.getFailureRequestTimeTotal().roundTo(SECONDS), 8); }
private void assertAllTimeSpentInQueueing(QueryState expectedState, Consumer<QueryStateMachine> stateTransition) { TestingTicker ticker = new TestingTicker(); QueryStateMachine stateMachine = createQueryStateMachineWithTicker(ticker); ticker.increment(7, MILLISECONDS); stateTransition.accept(stateMachine); assertEquals(stateMachine.getQueryState(), expectedState); QueryStats queryStats = stateMachine.getQueryInfo(Optional.empty()).getQueryStats(); assertEquals(queryStats.getQueuedTime(), new Duration(7, MILLISECONDS)); assertEquals(queryStats.getResourceWaitingTime(), new Duration(0, MILLISECONDS)); assertEquals(queryStats.getTotalPlanningTime(), new Duration(0, MILLISECONDS)); assertEquals(queryStats.getExecutionTime(), new Duration(0, MILLISECONDS)); assertEquals(queryStats.getFinishingTime(), new Duration(0, MILLISECONDS)); }
@Test public void testMinTries() { TestingTicker ticker = new TestingTicker(); ticker.increment(1, NANOSECONDS); Backoff backoff = new Backoff(3, new Duration(1, NANOSECONDS), ticker, ImmutableList.of(new Duration(10, MILLISECONDS))); ticker.increment(10, MICROSECONDS); // verify initial state assertEquals(backoff.getFailureCount(), 0); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 0); // first failure, should never fail assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 0); ticker.increment(14, SECONDS); // second failure under min failures, should not fail assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 14); ticker.increment(1, SECONDS); // last try failed assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 3); assertEquals(backoff.getFailureDuration().roundTo(SECONDS), 15); }
assertState(stateMachine, QUEUED); mockTicker.increment(50, MILLISECONDS); assertTrue(stateMachine.transitionToWaitingForResources()); assertState(stateMachine, WAITING_FOR_RESOURCES); mockTicker.increment(100, MILLISECONDS); assertTrue(stateMachine.transitionToPlanning()); assertState(stateMachine, PLANNING); mockTicker.increment(200, MILLISECONDS); assertTrue(stateMachine.transitionToStarting()); assertState(stateMachine, STARTING); mockTicker.increment(300, MILLISECONDS); assertTrue(stateMachine.transitionToRunning()); assertState(stateMachine, RUNNING); mockTicker.increment(400, MILLISECONDS); assertTrue(stateMachine.transitionToFinishing()); tryGetFutureValue(stateMachine.getStateChange(FINISHING), 2, SECONDS);
ticker.increment(1, NANOSECONDS); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 0); ticker.increment(backoffDelay, NANOSECONDS); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 1); ticker.increment(backoffDelay, NANOSECONDS); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 2); ticker.increment(backoffDelay, NANOSECONDS); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 4); ticker.increment(backoffDelay, NANOSECONDS); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 8); ticker.increment(backoffDelay, NANOSECONDS);
ticker.increment(delta.toMillis(), TimeUnit.MILLISECONDS); throw new RuntimeException("Foo"); };
TaskExecutor taskExecutor = new TaskExecutor(4, 8, 3, 4, ticker); taskExecutor.start(); ticker.increment(20, MILLISECONDS); assertEquals(driver1.getCompletedPhases(), 0); assertEquals(driver2.getCompletedPhases(), 0); ticker.increment(60, SECONDS); assertEquals(taskExecutor.getRunAwaySplitCount(), 0); ticker.increment(600, SECONDS); assertEquals(taskExecutor.getRunAwaySplitCount(), 2); verificationComplete.arriveAndAwaitAdvance(); ticker.increment(610, SECONDS); assertEquals(taskExecutor.getRunAwaySplitCount(), 0);
@Test(invocationCount = 100) public void testQuantaFairness() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(1, 2, 3, 4, ticker); taskExecutor.start(); ticker.increment(20, MILLISECONDS); try { TaskHandle shortQuantaTaskHandle = taskExecutor.addTask(new TaskId("shortQuanta", 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); TaskHandle longQuantaTaskHandle = taskExecutor.addTask(new TaskId("longQuanta", 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); Phaser globalPhaser = new Phaser(); TestingJob shortQuantaDriver = new TestingJob(ticker, new Phaser(), new Phaser(), globalPhaser, 10, 10); TestingJob longQuantaDriver = new TestingJob(ticker, new Phaser(), new Phaser(), globalPhaser, 10, 20); taskExecutor.enqueueSplits(shortQuantaTaskHandle, true, ImmutableList.of(shortQuantaDriver)); taskExecutor.enqueueSplits(longQuantaTaskHandle, true, ImmutableList.of(longQuantaDriver)); for (int i = 0; i < 11; i++) { globalPhaser.arriveAndAwaitAdvance(); } assertTrue(shortQuantaDriver.getCompletedPhases() >= 7 && shortQuantaDriver.getCompletedPhases() <= 8); assertTrue(longQuantaDriver.getCompletedPhases() >= 3 && longQuantaDriver.getCompletedPhases() <= 4); globalPhaser.arriveAndDeregister(); } finally { taskExecutor.stop(); } }
@Test(invocationCount = 100) public void testLevelMovement() { TestingTicker ticker = new TestingTicker(); TaskExecutor taskExecutor = new TaskExecutor(2, 2, 3, 4, ticker); taskExecutor.start(); ticker.increment(20, MILLISECONDS); try { TaskHandle testTaskHandle = taskExecutor.addTask(new TaskId("test", 0, 0), () -> 0, 10, new Duration(1, MILLISECONDS), OptionalInt.empty()); Phaser globalPhaser = new Phaser(); globalPhaser.bulkRegister(3); int quantaTimeMills = 500; int phasesPerSecond = 1000 / quantaTimeMills; int totalPhases = LEVEL_THRESHOLD_SECONDS[LEVEL_THRESHOLD_SECONDS.length - 1] * phasesPerSecond; TestingJob driver1 = new TestingJob(ticker, globalPhaser, new Phaser(), new Phaser(), totalPhases, quantaTimeMills); TestingJob driver2 = new TestingJob(ticker, globalPhaser, new Phaser(), new Phaser(), totalPhases, quantaTimeMills); taskExecutor.enqueueSplits(testTaskHandle, true, ImmutableList.of(driver1, driver2)); int completedPhases = 0; for (int i = 0; i < (LEVEL_THRESHOLD_SECONDS.length - 1); i++) { for (; (completedPhases / phasesPerSecond) < LEVEL_THRESHOLD_SECONDS[i + 1]; completedPhases++) { globalPhaser.arriveAndAwaitAdvance(); } assertEquals(testTaskHandle.getPriority().getLevel(), i + 1); } globalPhaser.arriveAndDeregister(); } finally { taskExecutor.stop(); } }
TaskExecutor taskExecutor = new TaskExecutor(1, 3, 3, 4, new MultilevelSplitQueue(2), ticker); taskExecutor.start(); ticker.increment(20, MILLISECONDS);
@Override public synchronized ListenableFuture<?> delay(Duration duration) { delays.add(duration); ticker.increment(duration.toMillis(), MILLISECONDS); return Futures.immediateFuture(null); } }
@Test public void testCountDecays() { TestingTicker ticker = new TestingTicker(); DecayCounter counter = new DecayCounter(ExponentialDecay.oneMinute(), ticker); counter.add(1); ticker.increment(1, TimeUnit.MINUTES); assertTrue(Math.abs(counter.getCount() - 1 / Math.E) < 1e-9); }
@Test public void testCountDecays() { TestingTicker ticker = new TestingTicker(); DecayCounter counter = new DecayCounter(ExponentialDecay.oneMinute(), ticker); counter.add(1); ticker.increment(1, TimeUnit.MINUTES); assertTrue(Math.abs(counter.getCount() - 1 / Math.E) < 1e-9); }
@Test public void timeTry() throws Exception { TimeStat stat = new TimeStat(ticker); try (BlockTimer ignored = stat.time()) { ticker.increment(10, TimeUnit.MILLISECONDS); } TimeDistribution allTime = stat.getAllTime(); assertEquals(allTime.getCount(), 1.0); assertEquals(allTime.getMin(), 0.010); assertEquals(allTime.getMax(), 0.010); }
@Test public void testDecayedCounts() throws Exception { TestingTicker ticker = new TestingTicker(); QuantileDigest digest = new QuantileDigest(1, ExponentialDecay.computeAlpha(0.5, 60), ticker); addAll(digest, asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); // should have no compressions with so few values and the allowed error assertEquals(digest.getConfidenceFactor(), 0.0); ticker.increment(60, TimeUnit.SECONDS); addAll(digest, asList(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)); assertEquals(digest.getCount(), 15.0); }
@Test public void testAddAfterRescale() { TestingTicker ticker = new TestingTicker(); DecayCounter counter = new DecayCounter(ExponentialDecay.oneMinute(), ticker); counter.add(1); ticker.increment(1, TimeUnit.MINUTES); counter.add(2); double expected = 2 + 1 / Math.E; assertTrue(Math.abs(counter.getCount() - expected) < 1e-9); } }
@Test public void testAddAfterRescale() { TestingTicker ticker = new TestingTicker(); DecayCounter counter = new DecayCounter(ExponentialDecay.oneMinute(), ticker); counter.add(1); ticker.increment(1, TimeUnit.MINUTES); counter.add(2); double expected = 2 + 1 / Math.E; assertTrue(Math.abs(counter.getCount() - expected) < 1e-9); } }