Skip to content

Instantly share code, notes, and snippets.

@entzik
Created March 1, 2017 23:21
Show Gist options
  • Save entzik/189fa5476bd9ff360a43e7580f282b4b to your computer and use it in GitHub Desktop.
Save entzik/189fa5476bd9ff360a43e7580f282b4b to your computer and use it in GitHub Desktop.
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();
}
}
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);
}
}
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