From a1031d2dc105fa7e8d9ba0e2e0f12890181a55f7 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Wed, 10 Jul 2024 22:13:01 +0200 Subject: [PATCH] feat: added HdrHistogram-backed MeasureStore --- measure/pom.xml | 5 ++ .../DescriptiveStatisticsMeasureStore.java | 26 ++++--- .../measure/HdrHistogramMeasureStore.java | 69 +++++++++++++++++++ 3 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 measure/src/main/java/net/laprun/sustainability/power/measure/HdrHistogramMeasureStore.java diff --git a/measure/pom.xml b/measure/pom.xml index dff0b6e..446166e 100644 --- a/measure/pom.xml +++ b/measure/pom.xml @@ -23,6 +23,11 @@ commons-math3 3.6.1 + + org.hdrhistogram + HdrHistogram + 2.2.2 + diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/DescriptiveStatisticsMeasureStore.java b/measure/src/main/java/net/laprun/sustainability/power/measure/DescriptiveStatisticsMeasureStore.java index a416dfe..0e08df8 100644 --- a/measure/src/main/java/net/laprun/sustainability/power/measure/DescriptiveStatisticsMeasureStore.java +++ b/measure/src/main/java/net/laprun/sustainability/power/measure/DescriptiveStatisticsMeasureStore.java @@ -3,12 +3,12 @@ import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; class DescriptiveStatisticsMeasureStore implements MeasureStore { + private final int totalIndex; private final DescriptiveStatistics[] measures; - private final DescriptiveStatistics total; public DescriptiveStatisticsMeasureStore(int componentsNumber, int initialWindow) { - total = new DescriptiveStatistics(initialWindow); - this.measures = new DescriptiveStatistics[componentsNumber]; + this.measures = new DescriptiveStatistics[componentsNumber + 1]; + totalIndex = componentsNumber; for (int i = 0; i < measures.length; i++) { measures[i] = new DescriptiveStatistics(initialWindow); } @@ -16,31 +16,39 @@ public DescriptiveStatisticsMeasureStore(int componentsNumber, int initialWindow @Override public void recordComponentValue(int component, double value) { - measures[component].addValue(value); + getMeasure(component).addValue(value); + } + + private DescriptiveStatistics getMeasure(int component) { + return measures[component]; + } + + private DescriptiveStatistics getTotalMeasure() { + return getMeasure(totalIndex); } @Override public void recordTotal(double value) { - total.addValue(value); + getTotalMeasure().addValue(value); } @Override public double getMeasuredTotal() { - return total.getSum(); + return getTotalMeasure().getSum(); } @Override public double getComponentStandardDeviation(int component) { - return measures[component].getStandardDeviation(); + return getMeasure(component).getStandardDeviation(); } @Override public double getTotalStandardDeviation() { - return total.getStandardDeviation(); + return getTotalMeasure().getStandardDeviation(); } @Override public double[] getComponentRawValues(int component) { - return measures[component].getValues(); + return getMeasure(component).getValues(); } } diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/HdrHistogramMeasureStore.java b/measure/src/main/java/net/laprun/sustainability/power/measure/HdrHistogramMeasureStore.java new file mode 100644 index 0000000..1d5c566 --- /dev/null +++ b/measure/src/main/java/net/laprun/sustainability/power/measure/HdrHistogramMeasureStore.java @@ -0,0 +1,69 @@ +package net.laprun.sustainability.power.measure; + +import org.HdrHistogram.HistogramIterationValue; +import org.HdrHistogram.IntCountsHistogram; + +public class HdrHistogramMeasureStore implements MeasureStore { + private static final int HIGHEST_TRACKABLE_VALUE = 1_000_000; + private static final int NUMBER_OF_SIGNIFICANT_VALUE_DIGITS = 4; + private static final int CONVERSION_FACTOR = 1000; + private final IntCountsHistogram[] measures; + private final int totalIndex; + private double accumulatedTotal; + + public HdrHistogramMeasureStore(int componentsNumber, int initialWindow) { + totalIndex = componentsNumber; + measures = new IntCountsHistogram[componentsNumber + 1]; + for (int i = 0; i < measures.length; i++) { + measures[i] = new IntCountsHistogram(HIGHEST_TRACKABLE_VALUE, + NUMBER_OF_SIGNIFICANT_VALUE_DIGITS); + } + } + + private IntCountsHistogram getMeasure(int component) { + return measures[component]; + } + + private IntCountsHistogram getTotalMeasure() { + return getMeasure(totalIndex); + } + + @Override + public void recordComponentValue(int component, double value) { + getMeasure(component).recordValue((long) (CONVERSION_FACTOR * value)); + } + + @Override + public void recordTotal(double value) { + getTotalMeasure().recordValue((long) (CONVERSION_FACTOR * value)); + accumulatedTotal += value; + } + + @Override + public double getMeasuredTotal() { + return accumulatedTotal; + } + + @Override + public double getComponentStandardDeviation(int component) { + return getMeasure(component).getStdDeviation() / CONVERSION_FACTOR; + } + + @Override + public double getTotalStandardDeviation() { + // not unbiased so tests will fail + return getTotalMeasure().getStdDeviation(); + } + + @Override + public double[] getComponentRawValues(int component) { + final var measure = getMeasure(component); + final var totalCount = measure.getTotalCount(); + final var result = new double[(int) totalCount]; + int index = 0; + for (HistogramIterationValue value : measure.recordedValues()) { + result[index++] = (double) value.getValueIteratedTo() / CONVERSION_FACTOR; + } + return result; + } +}