0a23bbdec7c7a6586ac16a5b7791a14e71ed9993
java/com.sap.sse.common.test/META-INF/MANIFEST.MF
| ... | ... | @@ -18,3 +18,4 @@ Require-Bundle: org.mockito.mockito-core;bundle-version="1.9.5", |
| 18 | 18 | net.bytebuddy.byte-buddy-agent;bundle-version="1.14.12" |
| 19 | 19 | Export-Package: com.sap.sse.common.test |
| 20 | 20 | Automatic-Module-Name: com.sap.sse.common.test |
| 21 | +Import-Package: com.sap.sse.testutils |
java/com.sap.sse.common.test/src/com/sap/sse/common/test/KadaneExtremeSubsequenceFinderTest.java
| ... | ... | @@ -3,17 +3,27 @@ package com.sap.sse.common.test; |
| 3 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 4 | 4 | import static org.junit.jupiter.api.Assertions.assertTrue; |
| 5 | 5 | |
| 6 | +import java.io.IOException; |
|
| 6 | 7 | import java.util.Random; |
| 7 | 8 | import java.util.TreeSet; |
| 9 | +import java.util.logging.Logger; |
|
| 8 | 10 | |
| 11 | +import org.junit.jupiter.api.AfterAll; |
|
| 9 | 12 | import org.junit.jupiter.api.Test; |
| 10 | 13 | |
| 11 | 14 | import com.sap.sse.common.scalablevalue.KadaneExtremeSubsequenceFinder; |
| 12 | 15 | import com.sap.sse.common.scalablevalue.ScalableDouble; |
| 16 | +import com.sap.sse.testutils.Measurement; |
|
| 17 | +import com.sap.sse.testutils.MeasurementCase; |
|
| 18 | +import com.sap.sse.testutils.MeasurementXMLFile; |
|
| 13 | 19 | |
| 14 | 20 | public abstract class KadaneExtremeSubsequenceFinderTest { |
| 15 | 21 | private static final double EPSILON = 0.00000001; |
| 22 | + private static final Logger logger = Logger.getLogger(KadaneExtremeSubsequenceFinderTest.class.getName()); |
|
| 23 | + |
|
| 16 | 24 | protected KadaneExtremeSubsequenceFinder<Double, Double, ScalableDouble> finder; |
| 25 | + private static Random random = new Random(); |
|
| 26 | + private static final MeasurementXMLFile performanceReport = new MeasurementXMLFile(KadaneExtremeSubsequenceFinderTest.class); |
|
| 17 | 27 | |
| 18 | 28 | @Test |
| 19 | 29 | public void testSimplePositiveSequence() { |
| ... | ... | @@ -137,42 +147,59 @@ public abstract class KadaneExtremeSubsequenceFinderTest { |
| 137 | 147 | } |
| 138 | 148 | |
| 139 | 149 | @Test |
| 140 | - public void performanceTestWithRandomRemove() { |
|
| 141 | - final Random random = new Random(); |
|
| 150 | + public void performanceTestWithRandomRemove() throws IOException { |
|
| 151 | + final MeasurementCase performanceMeasurement = performanceReport.addCase("PerformanceTestWithRandomRemove"); |
|
| 142 | 152 | final int NODES = 10000; |
| 143 | 153 | for (int i=0; i<NODES; i++) { |
| 144 | 154 | finder.add(new ScalableDouble(random.nextDouble()-0.5)); |
| 145 | 155 | } |
| 146 | 156 | assertEquals(NODES, finder.size()); |
| 157 | + finder.resetStats(); |
|
| 147 | 158 | for (int i=0; i<NODES/2; i++) { |
| 148 | 159 | finder.remove(random.nextInt(finder.size())); |
| 149 | 160 | } |
| 150 | 161 | assertEquals(NODES-NODES/2, finder.size()); |
| 162 | + performanceMeasurement.addMeasurement(new Measurement("minChangePropagationCount", finder.getAverageMinChangePropagationSteps())); |
|
| 163 | + performanceMeasurement.addMeasurement(new Measurement("maxChangePropagationCount", finder.getAverageMaxChangePropagationSteps())); |
|
| 164 | + logger.info("Stats after random remove: " + finder.toString()); |
|
| 151 | 165 | } |
| 152 | 166 | |
| 153 | 167 | @Test |
| 154 | - public void performanceTestWithRemoveFromBeginning() { |
|
| 155 | - final Random random = new Random(); |
|
| 168 | + public void performanceTestWithRemoveFromBeginning() throws IOException { |
|
| 169 | + final MeasurementCase performanceMeasurement = performanceReport.addCase("PerformanceTestWithRemoveFromBeginning"); |
|
| 156 | 170 | final int NODES = 10000; |
| 157 | 171 | for (int i=0; i<NODES; i++) { |
| 158 | 172 | finder.add(new ScalableDouble(random.nextDouble()-0.5)); |
| 159 | 173 | } |
| 160 | 174 | assertEquals(NODES, finder.size()); |
| 175 | + finder.resetStats(); |
|
| 161 | 176 | for (int i=0; i<NODES/2; i++) { |
| 162 | 177 | finder.remove(0); |
| 163 | 178 | } |
| 164 | 179 | assertEquals(NODES-NODES/2, finder.size()); |
| 180 | + performanceMeasurement.addMeasurement(new Measurement("minChangePropagationCount", finder.getAverageMinChangePropagationSteps())); |
|
| 181 | + performanceMeasurement.addMeasurement(new Measurement("maxChangePropagationCount", finder.getAverageMaxChangePropagationSteps())); |
|
| 182 | + logger.info("Stats after removing from beginning: " + finder.toString()); |
|
| 165 | 183 | } |
| 166 | 184 | |
| 167 | 185 | @Test |
| 168 | - public void performanceTestWithPruneFromBeginning() { |
|
| 169 | - final Random random = new Random(); |
|
| 186 | + public void performanceTestWithPruneFromBeginning() throws IOException { |
|
| 187 | + final MeasurementCase performanceMeasurement = performanceReport.addCase("PerformanceTestWithPruneFromBeginning"); |
|
| 170 | 188 | final int NODES = 10000; |
| 171 | 189 | for (int i=0; i<NODES; i++) { |
| 172 | 190 | finder.add(new ScalableDouble(random.nextDouble()-0.5)); |
| 173 | 191 | } |
| 174 | 192 | assertEquals(NODES, finder.size()); |
| 193 | + finder.resetStats(); |
|
| 175 | 194 | finder.removeFirst(NODES/2); |
| 176 | 195 | assertEquals(NODES-NODES/2, finder.size()); |
| 196 | + performanceMeasurement.addMeasurement(new Measurement("minChangePropagationCount", finder.getAverageMinChangePropagationSteps())); |
|
| 197 | + performanceMeasurement.addMeasurement(new Measurement("maxChangePropagationCount", finder.getAverageMaxChangePropagationSteps())); |
|
| 198 | + logger.info("Stats after pruning from beginning: " + finder.toString()); |
|
| 199 | + } |
|
| 200 | + |
|
| 201 | + @AfterAll |
|
| 202 | + public static void writeMeasurements() throws IOException { |
|
| 203 | + performanceReport.write(); |
|
| 177 | 204 | } |
| 178 | 205 | } |
java/com.sap.sse.common/src/com/sap/sse/common/scalablevalue/KadaneExtremeSubsequenceFinder.java
| ... | ... | @@ -68,4 +68,20 @@ public interface KadaneExtremeSubsequenceFinder<ValueType, AveragesTo extends Co |
| 68 | 68 | * slightly different from how indices may be handled in some other from/to collection operations. |
| 69 | 69 | */ |
| 70 | 70 | int getEndIndexOfMinSumSequence(); |
| 71 | + |
|
| 72 | + /** |
|
| 73 | + * @return statistics: average number of propagation steps when a change affected a minimum sum sub-sequence |
|
| 74 | + */ |
|
| 75 | + int getAverageMinChangePropagationSteps(); |
|
| 76 | + |
|
| 77 | + /** |
|
| 78 | + * @return statistics: average number of propagation steps when a change affected a maximum sum sub-sequence |
|
| 79 | + */ |
|
| 80 | + int getAverageMaxChangePropagationSteps(); |
|
| 81 | + |
|
| 82 | + /** |
|
| 83 | + * Resets the statistics on change propagation steps as returned by {@link #getAverageMinChangePropagationSteps()} |
|
| 84 | + * and {@link #getAverageMaxChangePropagationSteps()}. |
|
| 85 | + */ |
|
| 86 | + void resetStats(); |
|
| 71 | 87 | } |
java/com.sap.sse.common/src/com/sap/sse/common/scalablevalue/KadaneExtremeSubsequenceFinderLinkedNodesImpl.java
| ... | ... | @@ -509,4 +509,29 @@ public class KadaneExtremeSubsequenceFinderLinkedNodesImpl<ValueType, AveragesTo |
| 509 | 509 | final Iterable<Node<ValueType, AveragesTo, T>> nodeIterable = ()->nodeIterator(nodeWhereBestMinSumSubSequenceEnds.getStartOfMinSumSubSequenceEndingHere(), nodeWhereBestMinSumSubSequenceEnds); |
| 510 | 510 | return Util.map(nodeIterable, node->node.getValue()).iterator(); |
| 511 | 511 | } |
| 512 | + |
|
| 513 | + @Override |
|
| 514 | + public int getAverageMinChangePropagationSteps() { |
|
| 515 | + return minChangePropagationsCount == 0 ? 0 : minChangePropagationStepsSum / minChangePropagationsCount; |
|
| 516 | + } |
|
| 517 | + |
|
| 518 | + @Override |
|
| 519 | + public int getAverageMaxChangePropagationSteps() { |
|
| 520 | + return maxChangePropagationsCount == 0 ? 0 : maxChangePropagationStepsSum / maxChangePropagationsCount; |
|
| 521 | + } |
|
| 522 | + |
|
| 523 | + @Override |
|
| 524 | + public void resetStats() { |
|
| 525 | + minChangePropagationStepsSum = 0; |
|
| 526 | + minChangePropagationsCount = 0; |
|
| 527 | + maxChangePropagationStepsSum = 0; |
|
| 528 | + maxChangePropagationsCount = 0; |
|
| 529 | + } |
|
| 530 | + |
|
| 531 | + @Override |
|
| 532 | + public String toString() { |
|
| 533 | + return "KadaneExtremeSubsequenceFinderLinkedNodesImpl [size=" + size |
|
| 534 | + + ", minChangePropagationStepsAvg=" + minChangePropagationStepsSum / minChangePropagationsCount |
|
| 535 | + + ", maxChangePropagationStepsAvg=" + maxChangePropagationStepsSum / maxChangePropagationsCount + "]"; |
|
| 536 | + } |
|
| 512 | 537 | } |