Created
March 1, 2017 23:21
-
-
Save entzik/189fa5476bd9ff360a43e7580f282b4b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Calendar; | |
import java.util.function.Consumer; | |
/** | |
* Created by emilkirschner on 13/02/17. | |
*/ | |
class BaseBenchmarkState { | |
protected void generateTime(Consumer<Long> consumer) { | |
for (int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) { | |
for (int day = 0; day <= 28; day++) { | |
for (int hourOfDay = 0; hourOfDay < 24; hourOfDay++) { | |
for (int minute = 0; minute < 60; minute++) { | |
for (int seconds = 0; seconds < 60; seconds++) { | |
Calendar calendar = Calendar.getInstance(); | |
calendar.set(2014, month, day, hourOfDay, minute, seconds); | |
calendar.set(Calendar.MILLISECOND, 0); | |
final long timeInMillis = calendar.getTimeInMillis(); | |
consumer.accept(timeInMillis); | |
} | |
} | |
} | |
} | |
} | |
} | |
protected long getEndTime(int year, int month) { | |
final Calendar endCalendar = Calendar.getInstance(); | |
endCalendar.set(Calendar.YEAR, year); | |
endCalendar.set(Calendar.MONTH, month); | |
endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
endCalendar.set(Calendar.HOUR_OF_DAY, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MINUTE, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.SECOND, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MILLISECOND, endCalendar.getMaximum(Calendar.MILLISECOND)); | |
return endCalendar.getTimeInMillis(); | |
} | |
protected long getStartTime(int year, int month) { | |
final Calendar startCalendar = Calendar.getInstance(); | |
startCalendar.set( | |
year, | |
month, | |
startCalendar.getMinimum(Calendar.DAY_OF_MONTH), | |
startCalendar.getMinimum(Calendar.HOUR_OF_DAY), | |
startCalendar.getMinimum(Calendar.MINUTE), | |
startCalendar.getMinimum(Calendar.SECOND) | |
); | |
startCalendar.set(Calendar.MILLISECOND, startCalendar.getMinimum(Calendar.MILLISECOND)); | |
return startCalendar.getTimeInMillis(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.openjdk.jmh.annotations.*; | |
import org.openjdk.jmh.infra.Blackhole; | |
import java.util.*; | |
import java.util.concurrent.TimeUnit; | |
import java.util.concurrent.atomic.AtomicInteger; | |
public class EnvObservationProcessorBenchmark { | |
public static final int CAPACITY = 12 * 30 * 24 * 60 * 60 + 1; | |
@State(Scope.Thread) | |
public static class BenchmarkState extends BaseBenchmarkState{ | |
final EnvObsTimeSeries envObservationColumnarStore = new EnvObsTimeSeries(CAPACITY); | |
@Setup(Level.Trial) | |
public void doSetup() { | |
generateTime(timeInMillis -> envObservationColumnarStore.emplace(timeInMillis, Math.random(), Math.random(), Math.random())); | |
} | |
@TearDown(Level.Trial) | |
public void doTearDown() { | |
} | |
public EnvObsTimeSeries getEnvObservationColumnarStore() { | |
return envObservationColumnarStore; | |
} | |
} | |
@State(Scope.Thread) | |
public static class ClassicBenchmarkState extends BaseBenchmarkState{ | |
final ArrayList<EnvObservation> envObservationColumnarList = new ArrayList<>(); | |
@Setup(Level.Trial) | |
public void doSetup() { | |
generateTime(timeInMillis -> envObservationColumnarList.add(new EnvObservationImpl(timeInMillis, Math.random(), Math.random(), Math.random()))); | |
} | |
@TearDown(Level.Trial) | |
public void doTearDown() { | |
} | |
public List<EnvObservation> getEnvObservationColumnarList(int year, int month) { | |
final long startTime = getStartTime(year, month); | |
final long endTime = getEndTime(year, month); | |
final int[] ints = extractTimeSlice(startTime, endTime); | |
return envObservationColumnarList.subList(ints[0], ints[1]); | |
} | |
private int[] extractTimeSlice(long startTime, long endTime) { | |
int start = Collections.binarySearch(envObservationColumnarList, new EnvObservationImpl(startTime, 0, 0, 0), (o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp())); | |
if (start < 0) | |
start = (-start) - 1; | |
int end = Collections.binarySearch(envObservationColumnarList, new EnvObservationImpl(endTime, 0, 0, 0), (o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp())); | |
if (end < 0) | |
end = (-end) - 1; | |
return new int[]{start, end}; | |
} | |
} | |
@State(Scope.Thread) | |
public static class ClassicBenchmarkStateShuffled extends BaseBenchmarkState { | |
final ArrayList<EnvObservation> envObservationColumnarList = new ArrayList<>(); | |
@Setup(Level.Trial) | |
public void doSetup() { | |
generateTime(timeInMillis -> envObservationColumnarList.add(new EnvObservationImpl(timeInMillis, Math.random(), Math.random(), Math.random()))); | |
// shuffle | |
for (int i = 0; i < envObservationColumnarList.size(); i +=4) { | |
int p1 = (int)(Math.random() * envObservationColumnarList.size()); | |
int p2 = (int)(Math.random() * envObservationColumnarList.size()); | |
EnvObservation p = envObservationColumnarList.get(p1); | |
envObservationColumnarList.set(p1, envObservationColumnarList.get(p2)); | |
envObservationColumnarList.set(p2, p); | |
} | |
// reset timestamps | |
AtomicInteger crt = new AtomicInteger(0); | |
generateTime(timeStamp -> envObservationColumnarList.get(crt.getAndIncrement()).setTimeStamp(timeStamp)); | |
} | |
@TearDown(Level.Trial) | |
public void doTearDown() { | |
} | |
public List<EnvObservation> getEnvObservationColumnarList(int year, int month) { | |
final long startTime = getStartTime(year, month); | |
final long endTime = getEndTime(year, month); | |
final int[] ints = extractTimeSlice(startTime, endTime); | |
return envObservationColumnarList.subList(ints[0], ints[1]); | |
} | |
private int[] extractTimeSlice(long startTime, long endTime) { | |
int start = Collections.binarySearch(envObservationColumnarList, new EnvObservationImpl(startTime, 0, 0, 0), (o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp())); | |
if (start < 0) | |
start = (-start) - 1; | |
int end = Collections.binarySearch(envObservationColumnarList, new EnvObservationImpl(endTime, 0, 0, 0), (o1, o2) -> (int) (o1.getTimestamp() - o2.getTimestamp())); | |
if (end < 0) | |
end = (-end) - 1; | |
return new int[]{start, end}; | |
} | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void streamBenchmark(BenchmarkState state, Blackhole bh) { | |
final OptionalDouble optionalDouble = EnvObsevationsProcessor.averageMonthlyTemperatureWithPrimitiveStream(state.getEnvObservationColumnarStore(), 2014, Calendar.MARCH); | |
bh.consume(optionalDouble); | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void cursorBenchmark(BenchmarkState state, Blackhole bh) { | |
final OptionalDouble optionalDouble = EnvObsevationsProcessor.averageMonthlyTemperatureWithCursor(state.getEnvObservationColumnarStore(), 2014, Calendar.MARCH); | |
bh.consume(optionalDouble); | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void iteratorBenchmark(BenchmarkState state, Blackhole bh) { | |
final OptionalDouble optionalDouble = EnvObsevationsProcessor.averageMonthlyTemperatureWithObjectItertor(state.getEnvObservationColumnarStore(), 2014, Calendar.MARCH); | |
bh.consume(optionalDouble); | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void objectStreamBenchmark(BenchmarkState state, Blackhole bh) { | |
final OptionalDouble optionalDouble = EnvObsevationsProcessor.averageMonthlyTemperatureWithObjectStream(state.getEnvObservationColumnarStore(), 2014, Calendar.MARCH); | |
bh.consume(optionalDouble); | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void classicBenchmark(ClassicBenchmarkState state, Blackhole bh) { | |
final OptionalDouble optionalDouble = state.getEnvObservationColumnarList(2014, Calendar.MARCH).stream().mapToDouble(EnvObservation::getTemperature).average(); | |
bh.consume(optionalDouble); | |
} | |
@Benchmark | |
@BenchmarkMode({Mode.Throughput, Mode.SampleTime}) | |
@OutputTimeUnit(TimeUnit.MILLISECONDS) | |
public void classicBenchmarkShuffled(ClassicBenchmarkStateShuffled state, Blackhole bh) { | |
final OptionalDouble optionalDouble = state.getEnvObservationColumnarList(2014, Calendar.MARCH).stream().mapToDouble(EnvObservation::getTemperature).average(); | |
bh.consume(optionalDouble); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Calendar; | |
import java.util.Iterator; | |
import java.util.OptionalDouble; | |
import java.util.stream.Collectors; | |
public class EnvObsevationsProcessor { | |
public static OptionalDouble averageMonthlyTemperatureWithPrimitiveStream(EnvObsTimeSeries columnarStore, int year, int month) { | |
final Calendar startCalendar = Calendar.getInstance(); | |
startCalendar.set( | |
year, | |
month, | |
startCalendar.getMinimum(Calendar.DAY_OF_MONTH), | |
startCalendar.getMinimum(Calendar.HOUR_OF_DAY), | |
startCalendar.getMinimum(Calendar.MINUTE), | |
startCalendar.getMinimum(Calendar.SECOND) | |
); | |
startCalendar.set(Calendar.MILLISECOND, startCalendar.getMinimum(Calendar.MILLISECOND)); | |
final long startTime = startCalendar.getTimeInMillis(); | |
final Calendar endCalendar = Calendar.getInstance(); | |
endCalendar.set(Calendar.YEAR, year); | |
endCalendar.set(Calendar.MONTH, month); | |
endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
endCalendar.set(Calendar.HOUR_OF_DAY, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MINUTE, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.SECOND, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MILLISECOND, endCalendar.getMaximum(Calendar.MILLISECOND)); | |
final long endTime = endCalendar.getTimeInMillis(); | |
final int[] timeSliceIndexes = columnarStore.extractTimeSlice(startTime, endTime); | |
return columnarStore.getTemperatures(timeSliceIndexes[0], timeSliceIndexes[1]).average(); | |
} | |
public static OptionalDouble averageMonthlyTemperatureWithCursor(EnvObsTimeSeries columnarStore, int year, int month) { | |
final Calendar startCalendar = Calendar.getInstance(); | |
startCalendar.set( | |
year, | |
month, | |
startCalendar.getMinimum(Calendar.DAY_OF_MONTH), | |
startCalendar.getMinimum(Calendar.HOUR_OF_DAY), | |
startCalendar.getMinimum(Calendar.MINUTE), | |
startCalendar.getMinimum(Calendar.SECOND) | |
); | |
startCalendar.set(Calendar.MILLISECOND, startCalendar.getMinimum(Calendar.MILLISECOND)); | |
final long startTime = startCalendar.getTimeInMillis(); | |
final Calendar endCalendar = Calendar.getInstance(); | |
endCalendar.set(Calendar.YEAR, year); | |
endCalendar.set(Calendar.MONTH, month); | |
endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
endCalendar.set(Calendar.HOUR_OF_DAY, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MINUTE, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.SECOND, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MILLISECOND, endCalendar.getMaximum(Calendar.MILLISECOND)); | |
final long endTime = endCalendar.getTimeInMillis(); | |
final int[] timeSliceIndexes = columnarStore.extractTimeSlice(startTime, endTime); | |
double average = 0; | |
double count = timeSliceIndexes[1] - timeSliceIndexes[0]; | |
final EnvObsTimeSeries.ArbitraryAccessCursor cursor = columnarStore.get(0); | |
final int start = timeSliceIndexes[0]; | |
final int end = timeSliceIndexes[1]; | |
for (int i = start; i <= end; i ++) | |
average += (cursor.at(i).getTemperature() / count); | |
return OptionalDouble.of(average); | |
} | |
public static OptionalDouble averageMonthlyTemperatureWithObjectItertor(EnvObsTimeSeries columnarStore, int year, int month) { | |
final Calendar startCalendar = Calendar.getInstance(); | |
startCalendar.set( | |
year, | |
month, | |
startCalendar.getMinimum(Calendar.DAY_OF_MONTH), | |
startCalendar.getMinimum(Calendar.HOUR_OF_DAY), | |
startCalendar.getMinimum(Calendar.MINUTE), | |
startCalendar.getMinimum(Calendar.SECOND) | |
); | |
startCalendar.set(Calendar.MILLISECOND, startCalendar.getMinimum(Calendar.MILLISECOND)); | |
final long startTime = startCalendar.getTimeInMillis(); | |
final Calendar endCalendar = Calendar.getInstance(); | |
endCalendar.set(Calendar.YEAR, year); | |
endCalendar.set(Calendar.MONTH, month); | |
endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
endCalendar.set(Calendar.HOUR_OF_DAY, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MINUTE, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.SECOND, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MILLISECOND, endCalendar.getMaximum(Calendar.MILLISECOND)); | |
final long endTime = endCalendar.getTimeInMillis(); | |
final int[] timeSliceIndexes = columnarStore.extractTimeSlice(startTime, endTime); | |
double average = 0; | |
double count = timeSliceIndexes[1] - timeSliceIndexes[0]; | |
final int start = timeSliceIndexes[0]; | |
final int end = timeSliceIndexes[1]; | |
for (Iterator<EnvObservation> it = columnarStore.iterator(start, end); it.hasNext(); /* NOP */) | |
average += (it.next().getTemperature() / count); | |
return OptionalDouble.of(average); | |
} | |
public static OptionalDouble averageMonthlyTemperatureWithObjectStream(EnvObsTimeSeries columnarStore, int year, int month) { | |
final Calendar startCalendar = Calendar.getInstance(); | |
startCalendar.set( | |
year, | |
month, | |
startCalendar.getMinimum(Calendar.DAY_OF_MONTH), | |
startCalendar.getMinimum(Calendar.HOUR_OF_DAY), | |
startCalendar.getMinimum(Calendar.MINUTE), | |
startCalendar.getMinimum(Calendar.SECOND) | |
); | |
startCalendar.set(Calendar.MILLISECOND, startCalendar.getMinimum(Calendar.MILLISECOND)); | |
final long startTime = startCalendar.getTimeInMillis(); | |
final Calendar endCalendar = Calendar.getInstance(); | |
endCalendar.set(Calendar.YEAR, year); | |
endCalendar.set(Calendar.MONTH, month); | |
endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)); | |
endCalendar.set(Calendar.HOUR_OF_DAY, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MINUTE, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.SECOND, endCalendar.getMaximum(Calendar.HOUR_OF_DAY)); | |
endCalendar.set(Calendar.MILLISECOND, endCalendar.getMaximum(Calendar.MILLISECOND)); | |
final long endTime = endCalendar.getTimeInMillis(); | |
final int[] timeSliceIndexes = columnarStore.extractTimeSlice(startTime, endTime); | |
return columnarStore.stream(timeSliceIndexes[0], timeSliceIndexes[1]).mapToDouble(EnvObservation::getTemperature).average(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment