diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/AbstractPowerMeasure.java b/measure/src/main/java/net/laprun/sustainability/power/measure/AbstractPowerMeasure.java deleted file mode 100644 index 29a75fe1..00000000 --- a/measure/src/main/java/net/laprun/sustainability/power/measure/AbstractPowerMeasure.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.laprun.sustainability.power.measure; - -import java.util.List; - -import net.laprun.sustainability.power.SensorMetadata; - -public abstract class AbstractPowerMeasure implements PowerMeasure { - private final SensorMetadata sensorMetadata; - private final List measures; - - protected AbstractPowerMeasure(SensorMetadata sensorMetadata, List measures) { - this.sensorMetadata = sensorMetadata; - this.measures = measures; - } - - @Override - public List measures() { - return measures; - } - - @Override - public SensorMetadata metadata() { - return sensorMetadata; - } - - public int numberOfSamples() { - return measures.size(); - } - - double[] getComponentData(int componentIndex) { - return measures.parallelStream().mapToDouble(measure -> measure[componentIndex]).toArray(); - } -} diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/OngoingPowerMeasure.java b/measure/src/main/java/net/laprun/sustainability/power/measure/OngoingPowerMeasure.java index d32aea8b..ba731fc9 100644 --- a/measure/src/main/java/net/laprun/sustainability/power/measure/OngoingPowerMeasure.java +++ b/measure/src/main/java/net/laprun/sustainability/power/measure/OngoingPowerMeasure.java @@ -1,39 +1,59 @@ package net.laprun.sustainability.power.measure; import java.time.Duration; -import java.util.ArrayList; +import java.util.stream.IntStream; + +import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import net.laprun.sustainability.power.SensorMetadata; -public class OngoingPowerMeasure extends AbstractPowerMeasure { +public class OngoingPowerMeasure implements PowerMeasure { + private final SensorMetadata sensorMetadata; + private final DescriptiveStatistics[] measures; + private final DescriptiveStatistics total; private final long startedAt; + private final double[] averages; private double minTotal = Double.MAX_VALUE; private double maxTotal; - private final double[] totals; - private final double[] averages; + private int samples; - public OngoingPowerMeasure(SensorMetadata sensorMetadata, long duration, long frequency) { - super(sensorMetadata, new ArrayList<>((int) (duration / frequency))); + public OngoingPowerMeasure(SensorMetadata sensorMetadata, Duration duration, Duration frequency) { + this.sensorMetadata = sensorMetadata; startedAt = System.currentTimeMillis(); final var numComponents = metadata().componentCardinality(); - totals = new double[numComponents]; averages = new double[numComponents]; + + final var initialWindow = (int) (duration.toMillis() / frequency.toMillis()); + total = new DescriptiveStatistics(initialWindow); + this.measures = new DescriptiveStatistics[sensorMetadata.componentCardinality()]; + for (int i = 0; i < measures.length; i++) { + measures[i] = new DescriptiveStatistics(initialWindow); + } + } + + @Override + public int numberOfSamples() { + return samples; + } + + @Override + public SensorMetadata metadata() { + return sensorMetadata; } public void recordMeasure(double[] components) { - final var recorded = new double[components.length]; - System.arraycopy(components, 0, recorded, 0, components.length); - final var previousSize = numberOfSamples(); - measures().add(recorded); - - for (int i = 0; i < recorded.length; i++) { - totals[i] += recorded[i]; - averages[i] = averages[i] == 0 ? recorded[i] - : (previousSize * averages[i] + recorded[i]) / numberOfSamples(); + final var previousSize = samples; + samples++; + for (int component = 0; component < components.length; component++) { + final var componentValue = components[component]; + measures[component].addValue(componentValue); + averages[component] = averages[component] == 0 ? componentValue + : (previousSize * averages[component] + componentValue) / samples; } // record min / max totals - final var recordedTotal = PowerMeasure.sumOfSelectedComponents(recorded, metadata().totalComponents()); + final var recordedTotal = PowerMeasure.sumOfSelectedComponents(components, metadata().totalComponents()); + total.addValue(recordedTotal); if (recordedTotal < minTotal) { minTotal = recordedTotal; } @@ -44,7 +64,7 @@ public void recordMeasure(double[] components) { @Override public double total() { - return PowerMeasure.sumOfSelectedComponents(totals, metadata().totalComponents()); + return total.getSum(); } public Duration duration() { @@ -65,4 +85,19 @@ public double maxMeasuredTotal() { public double[] averagesPerComponent() { return averages; } + + public StdDev standardDeviations() { + final var cardinality = sensorMetadata.componentCardinality(); + final var stdDevs = new double[cardinality]; + IntStream.range(0, cardinality) + .parallel() + .forEach(component -> stdDevs[component] = measures[component].getStandardDeviation()); + + return new StdDev(total.getStandardDeviation(), stdDevs); + } + + @Override + public double[] getMeasuresFor(int component) { + return measures[component].getValues(); + } } diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/PowerMeasure.java b/measure/src/main/java/net/laprun/sustainability/power/measure/PowerMeasure.java index 825fc576..1e06e9dc 100644 --- a/measure/src/main/java/net/laprun/sustainability/power/measure/PowerMeasure.java +++ b/measure/src/main/java/net/laprun/sustainability/power/measure/PowerMeasure.java @@ -1,10 +1,6 @@ package net.laprun.sustainability.power.measure; import java.time.Duration; -import java.util.List; -import java.util.stream.IntStream; - -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import net.laprun.sustainability.power.SensorMetadata; @@ -28,6 +24,7 @@ static double sumOfSelectedComponents(double[] recorded, int... indices) { return componentSum; } + @SuppressWarnings("unused") static String asString(PowerMeasure measure) { final var durationInSeconds = measure.duration().getSeconds(); final var samples = measure.numberOfSamples(); @@ -62,30 +59,9 @@ default double average() { double maxMeasuredTotal(); - default StdDev standardDeviations() { - final var cardinality = metadata().componentCardinality(); - final var totalComponents = metadata().totalComponents(); - final DescriptiveStatistics[] perComponent = new DescriptiveStatistics[cardinality]; - for (int i = 0; i < perComponent.length; i++) { - perComponent[i] = new DescriptiveStatistics(); - } - final DescriptiveStatistics total = new DescriptiveStatistics(); - IntStream.range(0, cardinality).parallel() - .forEach(component -> { - measures().stream().parallel().forEach(measure -> { - perComponent[component].addValue(measure[component]); - total.addValue(sumOfSelectedComponents(measure, totalComponents)); - }); - }); - - final var stdDevs = new double[cardinality]; - for (int i = 0; i < perComponent.length; i++) { - stdDevs[i] = perComponent[i].getStandardDeviation(); - } - return new StdDev(total.getStandardDeviation(), stdDevs); - } + StdDev standardDeviations(); - List measures(); + double[] getMeasuresFor(int component); /** * Records the standard deviations for the aggregated energy comsumption value (as returned by {@link #total()}) and diff --git a/measure/src/main/java/net/laprun/sustainability/power/measure/StoppedPowerMeasure.java b/measure/src/main/java/net/laprun/sustainability/power/measure/StoppedPowerMeasure.java index ad7896a9..92a613ed 100644 --- a/measure/src/main/java/net/laprun/sustainability/power/measure/StoppedPowerMeasure.java +++ b/measure/src/main/java/net/laprun/sustainability/power/measure/StoppedPowerMeasure.java @@ -2,20 +2,34 @@ import java.time.Duration; -public class StoppedPowerMeasure extends AbstractPowerMeasure { +import net.laprun.sustainability.power.SensorMetadata; + +@SuppressWarnings("unused") +public class StoppedPowerMeasure implements PowerMeasure { + private final SensorMetadata sensorMetadata; + private final int samples; private final Duration duration; private final double total; private final double min; private final double max; private final double[] averages; + private final StdDev standardDeviations; + private final double[][] measures; public StoppedPowerMeasure(PowerMeasure powerMeasure) { - super(powerMeasure.metadata(), powerMeasure.measures()); + this.sensorMetadata = powerMeasure.metadata(); this.duration = powerMeasure.duration(); this.total = powerMeasure.total(); this.min = powerMeasure.minMeasuredTotal(); this.max = powerMeasure.maxMeasuredTotal(); this.averages = powerMeasure.averagesPerComponent(); + this.standardDeviations = powerMeasure.standardDeviations(); + this.samples = powerMeasure.numberOfSamples(); + final var cardinality = metadata().componentCardinality(); + measures = new double[cardinality][samples]; + for (int i = 0; i < cardinality; i++) { + measures[i] = powerMeasure.getMeasuresFor(i); + } } @Override @@ -42,4 +56,24 @@ public double total() { public double[] averagesPerComponent() { return averages; } + + @Override + public int numberOfSamples() { + return samples; + } + + @Override + public SensorMetadata metadata() { + return sensorMetadata; + } + + @Override + public StdDev standardDeviations() { + return standardDeviations; + } + + @Override + public double[] getMeasuresFor(int component) { + return measures[component]; + } } diff --git a/measure/src/test/java/net/laprun/sustainability/power/measure/OngoingPowerMeasureTest.java b/measure/src/test/java/net/laprun/sustainability/power/measure/OngoingPowerMeasureTest.java index f9a4d8ab..26cca244 100644 --- a/measure/src/test/java/net/laprun/sustainability/power/measure/OngoingPowerMeasureTest.java +++ b/measure/src/test/java/net/laprun/sustainability/power/measure/OngoingPowerMeasureTest.java @@ -2,6 +2,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import java.time.Duration; import java.util.Map; import org.junit.jupiter.api.Test; @@ -23,7 +24,7 @@ public int componentCardinality() { return 2; } }; - final var measure = new OngoingPowerMeasure(metadata, 1, 500); + final var measure = new OngoingPowerMeasure(metadata, Duration.ofSeconds(1), Duration.ofMillis(500)); final var components = new double[metadata.componentCardinality()]; components[0] = m1c1;