Skip to content

Commit e6f9b9c

Browse files
committed
refactor: move average out of measure and into compute / processor
1 parent db332b1 commit e6f9b9c

File tree

8 files changed

+99
-58
lines changed

8 files changed

+99
-58
lines changed

analysis/src/main/java/net/laprun/sustainability/power/analysis/Compute.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,27 @@ public enum Compute {
99

1010
public static double standardDeviation(PowerMeasure measure, int componentIndex) {
1111
return measure.getMeasuresFor(componentIndex).map(values -> {
12-
final var samples = measure.numberOfSamples();
12+
final var samples = values.length;
1313
if (samples <= 1) {
1414
return 0.0;
1515
}
16-
final double mean = measure.averagesPerComponent()[componentIndex];
16+
final double mean = average(measure, componentIndex);
1717
double geometricDeviationTotal = 0.0;
18-
for (int index = 0; index < samples; index++) {
19-
double deviation = values[index] - mean;
18+
for (double value : values) {
19+
double deviation = value - mean;
2020
geometricDeviationTotal += (deviation * deviation);
2121
}
2222
return FastMath.sqrt(geometricDeviationTotal / (samples - 1));
2323
}).orElse(0.0);
2424
}
25+
26+
public static double average(PowerMeasure measure, int componentIndex) {
27+
return measure.getMeasuresFor(componentIndex).map(values -> {
28+
double sum = 0.0;
29+
for (double value : values) {
30+
sum += value;
31+
}
32+
return sum / values.length;
33+
}).orElse(0.0);
34+
}
2535
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package net.laprun.sustainability.power.analysis;
2+
3+
public class MeanComponentProcessor implements ComponentProcessor {
4+
private double mean;
5+
private int count;
6+
7+
@Override
8+
public void recordComponentValue(double value, long timestamp) {
9+
final var previousSize = count;
10+
count++;
11+
mean = mean == 0 ? value : (previousSize * mean + value) / count;
12+
}
13+
}

analysis/src/test/java/ComputeTest.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ void standardDeviationShouldWork() {
5050
components[2] = m3c3;
5151
measure.recordMeasure(components);
5252

53-
final var c1Avg = measure.averagesPerComponent()[0];
54-
final var c2Avg = measure.averagesPerComponent()[1];
53+
final var c1Avg = Compute.average(measure, 0);
54+
final var c2Avg = Compute.average(measure, 1);
5555
final var stdVarForC1 = Math
5656
.sqrt((Math.pow(m1c1 - c1Avg, 2) + Math.pow(m2c1 - c1Avg, 2) + Math.pow(m3c1 - c1Avg, 2)) / (3 - 1));
5757
final var stdVarForC2 = Math
@@ -64,4 +64,47 @@ void standardDeviationShouldWork() {
6464
assertEquals(0, Compute.standardDeviation(measure, 2), 0.0001,
6565
"Standard Deviation did not match the expected value");
6666
}
67+
68+
@Test
69+
void averageShouldWork() {
70+
final var random = Random.from(RandomGenerator.getDefault());
71+
final var m1c1 = random.nextDouble();
72+
final var m1c2 = random.nextDouble();
73+
final var m1c3 = 0.0;
74+
final var m2c1 = random.nextDouble();
75+
final var m2c2 = random.nextDouble();
76+
final var m2c3 = 0.0;
77+
final var m3c1 = random.nextDouble();
78+
final var m3c2 = random.nextDouble();
79+
final var m3c3 = 0.0;
80+
81+
final var measure = new OngoingPowerMeasure(metadata);
82+
83+
final var components = new double[metadata.componentCardinality()];
84+
components[0] = m1c1;
85+
components[1] = m1c2;
86+
components[2] = m1c3;
87+
measure.recordMeasure(components);
88+
89+
components[0] = m2c1;
90+
components[1] = m2c2;
91+
components[2] = m2c3;
92+
measure.recordMeasure(components);
93+
94+
components[0] = m3c1;
95+
components[1] = m3c2;
96+
components[2] = m3c3;
97+
measure.recordMeasure(components);
98+
99+
final var c1Avg = Compute.average(measure, 0);
100+
final var c2Avg = Compute.average(measure, 1);
101+
final var c3Avg = Compute.average(measure, 2);
102+
103+
assertEquals((m1c1 + m2c1 + m3c1) / 3, c1Avg, 0.0001,
104+
"Average did not match the expected value");
105+
assertEquals((m1c2 + m2c2 + m3c2) / 3, c2Avg, 0.0001,
106+
"Average did not match the expected value");
107+
assertEquals(0, c3Avg, 0.0001,
108+
"Average did not match the expected value");
109+
}
67110
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package net.laprun.sustainability.power.measure;
2+
3+
public enum Compute {
4+
;
5+
6+
public static double sumOfComponents(double[] recorded) {
7+
var componentSum = 0.0;
8+
for (double value : recorded) {
9+
componentSum += value;
10+
}
11+
return componentSum;
12+
}
13+
14+
public static double sumOfSelectedComponents(double[] recorded, int... indices) {
15+
if (indices == null || indices.length == 0) {
16+
return sumOfComponents(recorded);
17+
}
18+
var componentSum = 0.0;
19+
for (int index : indices) {
20+
componentSum += recorded[index];
21+
}
22+
return componentSum;
23+
}
24+
}

measure/src/main/java/net/laprun/sustainability/power/measure/OngoingPowerMeasure.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public class OngoingPowerMeasure implements PowerMeasure {
1212
private static final int DEFAULT_SIZE = 32;
1313
private final SensorMetadata sensorMetadata;
1414
private final long startedAt;
15-
private final double[] averages;
1615
private final BitSet nonZeroComponents;
1716
private final int[] totalComponents;
1817
private final int totalIndex;
@@ -34,7 +33,6 @@ public OngoingPowerMeasure(SensorMetadata sensorMetadata, ComponentProcessor...
3433
measures = new double[measuresNb][DEFAULT_SIZE];
3534
timestamps = new long[DEFAULT_SIZE];
3635
totalIndex = numComponents;
37-
averages = new double[measuresNb];
3836
// we don't need to record the total component as a non-zero component since it's almost never zero and we compute the std dev separately
3937
nonZeroComponents = new BitSet(numComponents);
4038
totalComponents = sensorMetadata.totalComponents();
@@ -61,16 +59,12 @@ public void recordMeasure(double[] components) {
6159
nonZeroComponents.set(component);
6260
}
6361
recordComponentValue(component, componentValue);
64-
averages[component] = averages[component] == 0 ? componentValue
65-
: (previousSize * averages[component] + componentValue) / samples;
6662
}
6763

6864
// record min / max totals
69-
final var recordedTotal = PowerMeasure.sumOfSelectedComponents(components, totalComponents);
65+
final var recordedTotal = Compute.sumOfSelectedComponents(components, totalComponents);
7066
recordComponentValue(totalIndex, recordedTotal);
7167
accumulatedTotal += recordedTotal;
72-
averages[components.length] = averages[components.length] == 0 ? recordedTotal
73-
: (previousSize * averages[components.length] + recordedTotal) / samples;
7468
if (recordedTotal < minTotal) {
7569
minTotal = recordedTotal;
7670
}
@@ -119,11 +113,6 @@ public double maxMeasuredTotal() {
119113
return maxTotal;
120114
}
121115

122-
@Override
123-
public double[] averagesPerComponent() {
124-
return averages;
125-
}
126-
127116
@Override
128117
public Optional<double[]> getMeasuresFor(int component) {
129118
if (nonZeroComponents.get(component)) {

measure/src/main/java/net/laprun/sustainability/power/measure/PowerMeasure.java

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,14 @@
77
import net.laprun.sustainability.power.analysis.ComponentProcessor;
88

99
public interface PowerMeasure {
10-
private static double sumOfComponents(double[] recorded) {
11-
var componentSum = 0.0;
12-
for (double value : recorded) {
13-
componentSum += value;
14-
}
15-
return componentSum;
16-
}
17-
18-
static double sumOfSelectedComponents(double[] recorded, int... indices) {
19-
if (indices == null || indices.length == 0) {
20-
return sumOfComponents(recorded);
21-
}
22-
var componentSum = 0.0;
23-
for (int index : indices) {
24-
componentSum += recorded[index];
25-
}
26-
return componentSum;
27-
}
2810

2911
@SuppressWarnings("unused")
3012
static String asString(PowerMeasure measure) {
3113
final var durationInSeconds = measure.duration().getSeconds();
3214
final var samples = measure.numberOfSamples();
3315
final var measuredMilliWatts = measure.total();
34-
return String.format("%s / avg: %s [min: %.3f, max: %.3f] (%ds, %s samples)",
35-
readableWithUnit(measuredMilliWatts), readableWithUnit(measure.average()),
16+
return String.format("%s [min: %.3f, max: %.3f] (%ds, %s samples)",
17+
readableWithUnit(measuredMilliWatts),
3618
measure.minMeasuredTotal(), measure.maxMeasuredTotal(), durationInSeconds, samples);
3719
}
3820

@@ -46,16 +28,10 @@ static String readableWithUnit(double milliWatts) {
4628

4729
Duration duration();
4830

49-
default double average() {
50-
return total() / numberOfSamples();
51-
}
52-
5331
double total();
5432

5533
SensorMetadata metadata();
5634

57-
double[] averagesPerComponent();
58-
5935
double minMeasuredTotal();
6036

6137
double maxMeasuredTotal();

measure/src/main/java/net/laprun/sustainability/power/measure/StoppedPowerMeasure.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public class StoppedPowerMeasure implements PowerMeasure {
1414
private final double total;
1515
private final double min;
1616
private final double max;
17-
private final double[] averages;
1817
private final double[][] measures;
1918
private final ComponentProcessor[] processors;
2019

@@ -24,7 +23,6 @@ public StoppedPowerMeasure(PowerMeasure powerMeasure) {
2423
this.total = powerMeasure.total();
2524
this.min = powerMeasure.minMeasuredTotal();
2625
this.max = powerMeasure.maxMeasuredTotal();
27-
this.averages = powerMeasure.averagesPerComponent();
2826
this.samples = powerMeasure.numberOfSamples();
2927
final var cardinality = metadata().componentCardinality();
3028
measures = new double[cardinality][samples];
@@ -54,11 +52,6 @@ public double total() {
5452
return total;
5553
}
5654

57-
@Override
58-
public double[] averagesPerComponent() {
59-
return averages;
60-
}
61-
6255
@Override
6356
public int numberOfSamples() {
6457
return samples;

measure/src/test/java/net/laprun/sustainability/power/measure/OngoingPowerMeasureTest.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,7 @@ void testBasics() {
5757
assertThat(measure.getMeasuresFor(2)).isEmpty();
5858

5959
assertEquals(m1c1 + m1c2 + m1c3 + m2c1 + m2c2 + m2c3 + m3c1 + m3c2 + m3c3, measure.total());
60-
assertEquals((m1c1 + m1c2 + m1c3 + m2c1 + m2c2 + m2c3 + m3c1 + m3c2 + m3c3) / 3, measure.average());
6160
assertEquals(Stream.of(m1total, m2total, m3total).min(Double::compareTo).orElseThrow(), measure.minMeasuredTotal());
6261
assertEquals(Stream.of(m1total, m2total, m3total).max(Double::compareTo).orElseThrow(), measure.maxMeasuredTotal());
63-
final var c1Avg = measure.averagesPerComponent()[0];
64-
final var c2Avg = measure.averagesPerComponent()[1];
65-
final var c3Avg = measure.averagesPerComponent()[2];
66-
assertEquals((m1c1 + m2c1 + m3c1) / 3, c1Avg);
67-
assertEquals((m1c2 + m2c2 + m3c2) / 3, c2Avg);
68-
assertEquals(0, c3Avg);
6962
}
7063
}

0 commit comments

Comments
 (0)