package com.ldbc.driver.runtime.coordination;
import com.google.common.collect.Lists;
import com.ldbc.driver.generator.GeneratorFactory;
import com.ldbc.driver.generator.RandomDataGeneratorFactory;
import com.ldbc.driver.temporal.SystemTimeSource;
import com.ldbc.driver.temporal.TimeSource;
import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
public class LocalInitiatedTimeTrackerImplTest {
/*
------- PERFORMANCE -------
*/
@Ignore
@Test
public void comparePerformanceOfImplementations() throws CompletionTimeException {
int timesCountBigger = 1000000;
int timesCountSmaller = 10000;
int benchmarkRepetitions = 5;
long totalDuration_TreeMultiset_AddedRemovedImmediately = 0l;
long totalDuration_List_AddedRemovedImmediately = 0l;
long totalDuration_MinMaxPriorityQueue_AddedRemovedImmediately = 0l;
long totalDuration_TreeMultiset_AddAllThenRemoveAllSequentially = 0l;
long totalDuration_List_AddAllThenRemoveAllSequentially = 0l;
long totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllSequentially = 0l;
long totalDuration_TreeMultiSet_JustAdd = 0l;
long totalDuration_List_JustAdd = 0l;
long totalDuration_MinMaxPriorityQueue_JustAdd = 0l;
long totalDuration_TreeMultiset_AddAllThenRemoveAllRandomly = 0l;
long totalDuration_List_AddAllThenRemoveAllRandomly = 0l;
long totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllRandomly = 0l;
for (int i = 0; i < benchmarkRepetitions; i++) {
// ******
// Added Removed Immediately
// ******
totalDuration_TreeMultiset_AddedRemovedImmediately =
totalDuration_TreeMultiset_AddedRemovedImmediately +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAddedAndRemovedImmediately(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet(),
timesCountBigger
);
totalDuration_List_AddedRemovedImmediately =
totalDuration_List_AddedRemovedImmediately +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAddedAndRemovedImmediately(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList(),
timesCountBigger
);
totalDuration_MinMaxPriorityQueue_AddedRemovedImmediately =
totalDuration_MinMaxPriorityQueue_AddedRemovedImmediately +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAddedAndRemovedImmediately(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue(),
timesCountBigger
);
// ******
// Add All Then Remove All Sequentially
// ******
totalDuration_TreeMultiset_AddAllThenRemoveAllSequentially =
totalDuration_TreeMultiset_AddAllThenRemoveAllSequentially +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedSequentially(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet(),
timesCountSmaller
);
totalDuration_List_AddAllThenRemoveAllSequentially =
totalDuration_List_AddAllThenRemoveAllSequentially +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedSequentially(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList(),
timesCountSmaller
);
totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllSequentially =
totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllSequentially +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedSequentially(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue(),
timesCountSmaller
);
// ******
// Just Add
// ******
totalDuration_TreeMultiSet_JustAdd =
totalDuration_TreeMultiSet_JustAdd +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesJustAdd(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet(),
timesCountBigger
);
totalDuration_List_JustAdd =
totalDuration_List_JustAdd +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesJustAdd(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList(),
timesCountBigger
);
totalDuration_MinMaxPriorityQueue_JustAdd =
totalDuration_MinMaxPriorityQueue_JustAdd +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesJustAdd(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue(),
timesCountBigger
);
// ******
// Add All Then Remove All Randomly
// ******
totalDuration_TreeMultiset_AddAllThenRemoveAllRandomly =
totalDuration_TreeMultiset_AddAllThenRemoveAllRandomly +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedRandomly(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet(),
timesCountSmaller
);
totalDuration_List_AddAllThenRemoveAllRandomly =
totalDuration_List_AddAllThenRemoveAllRandomly +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedRandomly(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList(),
timesCountSmaller
);
totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllRandomly =
totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllRandomly +
performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedRandomly(
LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue(),
timesCountSmaller
);
}
System.out.println("TreeMultiSet (add " + timesCountBigger + "):\t\t\t\t\t\t\t\t\t" + totalDuration_TreeMultiSet_JustAdd + " <- add to large/growing");
System.out.println("List (add " + timesCountBigger + "):\t\t\t\t\t\t\t\t\t\t\t" + totalDuration_List_JustAdd + " <- add to large/growing");
System.out.println("MinMaxPriorityQueue (add " + timesCountBigger + "):\t\t\t\t\t\t\t" + totalDuration_MinMaxPriorityQueue_JustAdd + " <- add to large/growing");
System.out.println();
System.out.println("TreeMultiSet (add one/remove one x " + timesCountBigger + "):\t\t\t\t" + totalDuration_TreeMultiset_AddedRemovedImmediately + " <- add to small`,remove from small sequentially");
System.out.println("List (add one/remove one):\t\t\t\t\t\t\t\t\t" + totalDuration_List_AddedRemovedImmediately + " <- add to small,remove from small sequentially");
System.out.println("MinMaxPriorityQueue (add one/remove one x " + timesCountBigger + "):\t\t\t" + totalDuration_MinMaxPriorityQueue_AddedRemovedImmediately + " <- add to small,remove from small sequentially");
System.out.println();
System.out.println("TreeMultiSet (add " + timesCountSmaller + "/remove " + timesCountSmaller + " sequentially):\t\t\t" + totalDuration_TreeMultiset_AddAllThenRemoveAllSequentially + " <- add to large/growing, removal from large/growing sequentially");
System.out.println("List (add " + timesCountSmaller + "/remove " + timesCountSmaller + " sequentially):\t\t\t\t\t" + totalDuration_List_AddAllThenRemoveAllSequentially + " <- add to large/growing, removal from large/growing sequentially");
System.out.println("MinMaxPriorityQueue (add " + timesCountSmaller + "/remove " + timesCountSmaller + " sequentially):\t" + totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllSequentially + " <- add to large/growing, removal from large/growing sequentially");
System.out.println();
System.out.println("TreeMultiSet (add " + timesCountSmaller + "/remove " + timesCountSmaller + " randomly):\t\t\t\t" + totalDuration_TreeMultiset_AddAllThenRemoveAllRandomly + " <- add to large/growing, removal from large/growing randomly");
System.out.println("List (add " + timesCountSmaller + "/remove " + timesCountSmaller + " randomly):\t\t\t\t\t\t" + totalDuration_List_AddAllThenRemoveAllRandomly + " <- add to large/growing, removal from large/growing randomly");
System.out.println("MinMaxPriorityQueue (add " + timesCountSmaller + "/remove " + timesCountSmaller + " randomly):\t\t" + totalDuration_MinMaxPriorityQueue_AddAllThenRemoveAllRandomly + " <- add to large/growing, removal from large/growing randomly");
}
public long performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAddedAndRemovedImmediately(
LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker,
int timesCount) throws CompletionTimeException {
TimeSource timeSource = new SystemTimeSource();
GeneratorFactory gf = new GeneratorFactory(new RandomDataGeneratorFactory(42L));
Iterator<Long> times = gf.limit(
gf.incrementing(0l, 1l),
timesCount
);
long startTimeAsMilli = timeSource.nowAsMilli();
while (times.hasNext()) {
long time = times.next();
tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
long finishTime = timeSource.nowAsMilli();
return finishTime - startTimeAsMilli;
}
public long performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedSequentially(
LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker,
int timesCount) throws CompletionTimeException {
TimeSource timeSource = new SystemTimeSource();
GeneratorFactory gf = new GeneratorFactory(new RandomDataGeneratorFactory(42L));
List<Long> times = Lists.newArrayList(
gf.limit(
gf.incrementing(0l, 1l),
timesCount
)
);
long startTime = timeSource.nowAsMilli();
// add all times
for (long time : times) {
tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
// remove all times
for (long time : times) {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
long finishTime = timeSource.nowAsMilli();
return finishTime - startTime;
}
public long performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesAllAddedThenAllRemovedRandomly(
LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker,
int timesCount) throws CompletionTimeException {
TimeSource timeSource = new SystemTimeSource();
GeneratorFactory gf = new GeneratorFactory(new RandomDataGeneratorFactory(42L));
final List<Long> times = Lists.newArrayList(
gf.limit(
gf.incrementing(0l, 1l),
timesCount
)
);
// create iterator to add times from, in sequential order <-- requirement of tracker
Iterator<Long> timesToAdd = Lists.newArrayList(times).iterator();
// create iterator to remove times from, in random order
List<Long> timesToRemoveList = new ArrayList<>();
Iterator<Double> uniforms = gf.uniform(0.0, 1.0);
while (false == times.isEmpty()) {
int index = (int) Math.round(Math.floor(uniforms.next() * times.size()));
long timeToRemove = times.remove(index);
assertThat(timeToRemove, is(not(-1l)));
timesToRemoveList.add(timeToRemove);
}
assertThat(timesToRemoveList.size(), is(timesCount));
Iterator<Long> timesToRemove = timesToRemoveList.iterator();
long startTime = timeSource.nowAsMilli();
// add all times
while (timesToAdd.hasNext()) {
long time = timesToAdd.next();
tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
assertThat(tracker.uncompletedInitiatedTimes(), is(timesCount));
// remove all times
while (timesToRemove.hasNext()) {
long time = timesToRemove.next();
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
long finishTime = timeSource.nowAsMilli();
assertThat(tracker.uncompletedInitiatedTimes(), is(0));
return finishTime - startTime;
}
public long performanceOfLocalInitiatedTimeTrackerImplementationsWhenTimesJustAdd(
LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker,
int timesCount) throws CompletionTimeException {
TimeSource timeSource = new SystemTimeSource();
GeneratorFactory gf = new GeneratorFactory(new RandomDataGeneratorFactory(42L));
List<Long> times = Lists.newArrayList(
gf.limit(
gf.incrementing(0l, 1l),
timesCount
)
);
long startTime = timeSource.nowAsMilli();
// add all times
for (long time : times) {
tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(time);
tracker.uncompletedInitiatedTimes();
tracker.highestInitiatedTimeAsMilli();
}
long finishTime = timeSource.nowAsMilli();
return finishTime - startTime;
}
/*
------- CORRECTNESS -------
*/
@Test
public void shouldReturnNullsWhenNoTimesHaveBeenSubmitted_TreeMultiSetImplementation() {
shouldReturnNullsWhenNoTimesHaveBeenSubmitted(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet());
}
@Test
public void shouldReturnNullsWhenNoTimesHaveBeenSubmitted_ListImplementation() {
shouldReturnNullsWhenNoTimesHaveBeenSubmitted(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList());
}
@Test
public void shouldReturnNullsWhenNoTimesHaveBeenSubmitted_MinMaxPriorityQueueImplementation() {
shouldReturnNullsWhenNoTimesHaveBeenSubmitted(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue());
}
public void shouldReturnNullsWhenNoTimesHaveBeenSubmitted(LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker) {
// Given
// tracker
// When
// nothing
// Then
assertThat(tracker.highestInitiatedTimeAsMilli(), is(-1l));
boolean exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
assertThat(tracker.uncompletedInitiatedTimes(), is(0));
}
@Test
public void shouldBehaveAsExpectedUnderScenario1_TreeMultiSetImplementation() throws CompletionTimeException {
shouldBehaveAsExpectedUnderScenario1(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingTreeMultiSet());
}
@Test
public void shouldBehaveAsExpectedUnderScenario1_ListImplementation() throws CompletionTimeException {
shouldBehaveAsExpectedUnderScenario1(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingArrayList());
}
@Test
public void shouldBehaveAsExpectedUnderScenario1_MinMaxPriorityQueueImplementation() throws CompletionTimeException {
shouldBehaveAsExpectedUnderScenario1(LocalCompletionTimeStateManager.LocalInitiatedTimeTrackerImpl.createUsingMinMaxPriorityQueue());
}
public void shouldBehaveAsExpectedUnderScenario1(LocalCompletionTimeStateManager.LocalInitiatedTimeTracker tracker) throws CompletionTimeException {
// Given
// tracker
// When/Then
assertThat(tracker.highestInitiatedTimeAsMilli(), is(-1l));
boolean exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
assertThat(tracker.uncompletedInitiatedTimes(), is(0));
// [0]
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(0l), equalTo(0l));
assertThat(tracker.highestInitiatedTimeAsMilli(), is(0l));
assertThat(tracker.uncompletedInitiatedTimes(), is(1));
// [0]
exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
// [0,0]
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(0l), equalTo(0l));
assertThat(tracker.highestInitiatedTimeAsMilli(), is(0l));
assertThat(tracker.uncompletedInitiatedTimes(), is(2));
// [0,0]
exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
// [0,0,1,1,4,5]
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(1l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(1l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(4l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(5l), equalTo(0l));
assertThat(tracker.highestInitiatedTimeAsMilli(), is(5l));
assertThat(tracker.uncompletedInitiatedTimes(), is(6));
// [0,0,1,1,4,5,7,9,10,15]
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(7l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(9l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(10l), equalTo(0l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(15l), equalTo(0l));
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(10));
// [0,0,1,1,4,5,7,9,10,15]
exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(2l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
exceptionThrown = false;
try {
tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(3l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
// [ ,0,1,1,4,5,7,9,10,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(0l), is(0l));
// [ ,0,1,1,4, ,7,9,10,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(5l), is(0l));
// [ ,0,1,1,4, ,7,9, ,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(10l), is(0l));
// [ ,0,1,1,4, ,7,9, ,15]
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(7));
// [ , ,1,1,4, ,7,9, ,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(0l), is(1l));
// [ , ,1,1, , ,7,9, ,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(4l), is(1l));
// [ , ,1,1, , ,7, , ,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(9l), is(1l));
// [ , ,1,1, , ,7, , ,15]
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(4));
// [ , ,1,1, , ,7, , ,15,15,15]
exceptionThrown = false;
try {
tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(14l);
} catch (CompletionTimeException e) {
exceptionThrown = true;
}
assertThat(exceptionThrown, is(true));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(15l), equalTo(1l));
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(15l), equalTo(1l));
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(6));
// [ , ,1,1, , ,7, , , ,15,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(15l), is(1l));
// [ , ,1,1, , ,7, , , , ,15]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(15l), is(1l));
// [ , ,1,1, , ,7, , , , , ]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(15l), is(1l));
// [ , ,1,1, , ,7, , , , , ]
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(3));
// [ , , ,1, , ,7, , , , , ]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l), is(1l));
// [ , , , , , ,7, , , , , ]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(1l), is(7l));
// [ , , , , , ,7, , , , , ]
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(1));
// [ , , , , , , , , , , , ]
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(7l), is(15l));
// [ , , , , , , , , , , , ]
assertThat(tracker.highestInitiatedTimeAsMilli(), is(15l));
assertThat(tracker.uncompletedInitiatedTimes(), is(0));
for (int i = 16; i < 10000; i++) {
assertThat(tracker.addInitiatedTimeAndReturnLastKnownLowestTimeAsMilli(i), equalTo(16l));
}
for (int i = 16; i < 9999; i++) {
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(i), is(i + 1l));
}
assertThat(tracker.removeTimeAndReturnLastKnownLowestTimeAsMilli(9999l), is(9999l));
}
}