performance improvement

* pre-fill the buckets
* use LongObjHashMap to avoid boxing
This commit is contained in:
2022-11-20 16:37:05 +01:00
parent 65d4717c55
commit 7a82d4b09e
3 changed files with 58 additions and 17 deletions

View File

@@ -1,15 +1,13 @@
package org.lucares.pdb.plot.api;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import org.lucares.collections.LongObjHashMap;
import org.lucares.recommind.logs.GnuplotAxis;
public class BoxAggregator implements CustomAggregator, IndexedAggregator {
private static final double SPACE_BETWEEN_BARS = 0.6;
private Long index = null;
private Long numberOfDataSeries;
@@ -17,19 +15,20 @@ public class BoxAggregator implements CustomAggregator, IndexedAggregator {
private final Interval interval;
private final Map<Long, PercentilesAggregator> buckets = new HashMap<>();
private final LongObjHashMap<PercentilesAggregator> buckets;
public BoxAggregator(final PlotSettings settings) {
this.interval = settings.getInterval().get();
this.buckets = interval.getMiddleTimeBuckets(PercentilesAggregator::new);
}
@Override
public void addValue(final long epochMilli, final long value) {
final long bucketId = interval.toBucketMiddleTime(epochMilli);
buckets.putIfAbsent(bucketId, new PercentilesAggregator());
buckets.get(bucketId).addValue(epochMilli, value);
final PercentilesAggregator bucket = buckets.get(bucketId);
bucket.addValue(epochMilli, value);
}
@Override
@@ -76,9 +75,9 @@ public class BoxAggregator implements CustomAggregator, IndexedAggregator {
public String asCsv(final boolean renderLabels) {
final StringBuilder csv = new StringBuilder();
int i = 0;
for (final long bucketId : buckets.keySet()) {
final Percentiles percentiles = buckets.get(bucketId).getPercentiles();
buckets.forEachOrdered((final long bucketId, final PercentilesAggregator percentilesAggregator) -> {
final Percentiles percentiles = percentilesAggregator.getPercentiles();
csv.append(String.format(Locale.US, "%d,%d,%d,%d,%d,%d", //
bucketId / 1000, //
percentiles.get("0.000"), //
@@ -88,8 +87,8 @@ public class BoxAggregator implements CustomAggregator, IndexedAggregator {
percentiles.get("100.000")//
));
csv.append("\n");
i++;
}
});
return csv.toString();
}

View File

@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.lucares.collections.LongObjHashMap;
import org.lucares.pdb.api.DateTimeRange;
import org.lucares.pdb.datastore.internal.LongToDateBucket;
@@ -61,12 +62,15 @@ public class Interval {
return epochMilli - epochMilli % 3600000 + 1800000;
case DAY:
return epochMilli - epochMilli % 86400000 + 43200000;
// case WEEK:
// return "YYYY-ww"; // use week based year! Otherwise intervals over the year boundary will be wrong
// case MONTH:
// return "yyyy-MM";
// case YEAR:
// return "yyyy";
case WEEK:
return epochMilli - epochMilli % (7 * 24 * 3600 * 1000) + 7 * 24 * 3600 * 500; // use week based year!
// Otherwise intervals over
// the year boundary will be
// wrong
case MONTH:
return epochMilli - epochMilli % (30 * 24 * 3600 * 1000L) + 30 * 24 * 3600 * 500L;
case YEAR:
return epochMilli - epochMilli % (365 * 24 * 3600 * 1000L) + 365 * 24 * 3600 * 500L;
default:
throw new IllegalArgumentException("Unexpected value: " + intervalTimeUnit);
}
@@ -104,4 +108,21 @@ public class Interval {
return result;
}
public <T> LongObjHashMap<T> getMiddleTimeBuckets(final Supplier<T> initialValueSupplier) {
final LongObjHashMap<T> result = new LongObjHashMap<>();
long current = dateTimeRange.getStart().toInstant().toEpochMilli();
final long end = dateTimeRange.getEnd().toInstant().toEpochMilli() + intervalTimeUnit.toMillis();
while (current <= end) {
final long id = toBucketMiddleTime(current);
System.out.println("add bucket: " + id);
result.put(id, initialValueSupplier.get());
current += intervalTimeUnit.toMillis();
}
return result;
}
}

View File

@@ -34,4 +34,25 @@ public enum IntervalTimeUnit {
throw new IllegalArgumentException("Unexpected value: " + this);
}
}
public long toMillis() {
switch (this) {
case SECOND:
return 1000;
case MINUTE:
return 60 * 1000;
case HOUR:
return 3600 * 1000;
case DAY:
return 24 * 3600 * 1000;
case WEEK:
return 7 * 24 * 3600 * 1000;
case MONTH:
return 30 * 24 * 3600 * 1000L;
case YEAR:
return 365 * 24 * 3600 * 1000L;
default:
throw new IllegalArgumentException("Unexpected value: " + this);
}
}
}