From 881f0e5617a1d6bedd445639055313446ae56317 Mon Sep 17 00:00:00 2001 From: Morten Haraldsen Date: Thu, 12 Sep 2024 13:30:29 +0200 Subject: [PATCH] 1.4.2 --- pom.xml | 2 +- .../DurationPerformanceStatistics.java | 25 +++++---- .../statistics/PerformanceStatistics.java | 6 +-- .../ThroughputPerformanceStatistics.java | 36 +++++-------- .../com/ethlo/util/IndexedCollection.java | 2 + src/main/java/com/ethlo/util/LongList.java | 11 ++++ src/main/java/com/ethlo/util/MathUtil.java | 53 ------------------- .../ethlo/time/statistics/StatisticsTest.java | 53 +++++++++++++++++++ .../ThroughputPerformanceStatisticsTest.java | 25 --------- .../java/com/ethlo/util/LongListTest.java | 23 ++++++-- 10 files changed, 114 insertions(+), 122 deletions(-) delete mode 100644 src/main/java/com/ethlo/util/MathUtil.java create mode 100644 src/test/java/com/ethlo/time/statistics/StatisticsTest.java delete mode 100644 src/test/java/com/ethlo/time/statistics/ThroughputPerformanceStatisticsTest.java diff --git a/pom.xml b/pom.xml index 6cc4acc..63d18cd 100755 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ chronograph Chronograph Easy-to-use stopwatch for task performance statistics - 1.4.1 + 1.4.2 Apache License, Version 2.0 diff --git a/src/main/java/com/ethlo/time/statistics/DurationPerformanceStatistics.java b/src/main/java/com/ethlo/time/statistics/DurationPerformanceStatistics.java index 88a3257..6a79b89 100644 --- a/src/main/java/com/ethlo/time/statistics/DurationPerformanceStatistics.java +++ b/src/main/java/com/ethlo/time/statistics/DurationPerformanceStatistics.java @@ -26,13 +26,17 @@ import com.ethlo.util.IndexedCollection; import com.ethlo.util.IndexedCollectionStatistics; -import com.ethlo.util.MathUtil; public class DurationPerformanceStatistics extends PerformanceStatistics { public DurationPerformanceStatistics(final IndexedCollectionStatistics collectionStatistics, long totalInvocations, Duration elapsedTotal) { - super(collectionStatistics, totalInvocations, elapsedTotal); + super(collectionStatistics, totalInvocations, elapsedTotal.toNanos()); + } + + public DurationPerformanceStatistics(IndexedCollectionStatistics collectionStatistics) + { + super(collectionStatistics, collectionStatistics.size(), collectionStatistics.sum()); } @Override @@ -75,22 +79,17 @@ public Duration getStandardDeviation() { final IndexedCollection list = collectionStatistics.getList(); final int count = list.size(); - if (count == 0) - { - return Duration.ZERO; - } - final double average = getAverage().toNanos(); - BigDecimal sd = BigDecimal.valueOf(0); - for (long l : list) + final long mean = getAverage().toNanos(); + double standardDeviation = 0D; + for (long num : list) { - final double val = Math.pow((l - average) / (double) count, 2); - sd = sd.add(BigDecimal.valueOf(val)); + standardDeviation += Math.pow(num - mean, 2); } - return Duration.ofNanos(MathUtil.sqrt(sd).longValue()); + return Duration.ofNanos((long) Math.sqrt(standardDeviation / (double) count)); } public DurationPerformanceStatistics merge(final DurationPerformanceStatistics other) { - return new DurationPerformanceStatistics(this.collectionStatistics.merge(other.collectionStatistics), totalInvocations + other.totalInvocations, elapsedTotal.plus(other.elapsedTotal)); + return new DurationPerformanceStatistics(this.collectionStatistics.merge(other.collectionStatistics), totalInvocations + other.totalInvocations, Duration.ofNanos(elapsedTotal + other.elapsedTotal)); } } diff --git a/src/main/java/com/ethlo/time/statistics/PerformanceStatistics.java b/src/main/java/com/ethlo/time/statistics/PerformanceStatistics.java index e6b17f2..4d26fb0 100644 --- a/src/main/java/com/ethlo/time/statistics/PerformanceStatistics.java +++ b/src/main/java/com/ethlo/time/statistics/PerformanceStatistics.java @@ -28,9 +28,9 @@ public abstract class PerformanceStatistics { protected final IndexedCollectionStatistics collectionStatistics; protected final long totalInvocations; - protected final Duration elapsedTotal; + protected final long elapsedTotal; - public PerformanceStatistics(final IndexedCollectionStatistics collectionStatistics, long totalInvocations, Duration elapsedTotal) + public PerformanceStatistics(final IndexedCollectionStatistics collectionStatistics, long totalInvocations, long elapsedTotal) { this.collectionStatistics = collectionStatistics; this.totalInvocations = totalInvocations; @@ -44,7 +44,7 @@ public long getTotalInvocations() public Duration getElapsedTotal() { - return elapsedTotal; + return Duration.ofNanos(elapsedTotal); } public abstract T getAverage(); diff --git a/src/main/java/com/ethlo/time/statistics/ThroughputPerformanceStatistics.java b/src/main/java/com/ethlo/time/statistics/ThroughputPerformanceStatistics.java index ff38239..33dc179 100644 --- a/src/main/java/com/ethlo/time/statistics/ThroughputPerformanceStatistics.java +++ b/src/main/java/com/ethlo/time/statistics/ThroughputPerformanceStatistics.java @@ -20,14 +20,10 @@ * #L% */ -import java.math.BigDecimal; -import java.math.MathContext; -import java.math.RoundingMode; import java.time.Duration; import com.ethlo.util.IndexedCollection; import com.ethlo.util.IndexedCollectionStatistics; -import com.ethlo.util.MathUtil; public class ThroughputPerformanceStatistics extends PerformanceStatistics { @@ -35,7 +31,12 @@ public class ThroughputPerformanceStatistics extends PerformanceStatistics list = collectionStatistics.getList(); final int count = list.size(); - if (count == 0) - { - return 0D; - } - final double average = getAverage(); - BigDecimal sd = BigDecimal.valueOf(0); - for (long l : list) + final Double mean = getAverage(); + double standardDeviation = 0D; + for (long num : list) { - final double val = Math.pow(((D_NANOS / l) - average) / (double) count, 2); - sd = sd.add(BigDecimal.valueOf(val)); + standardDeviation += Math.pow(num - mean, 2); } - return MathUtil.sqrt(sd).doubleValue(); + return Math.sqrt(standardDeviation / (double) count); } public ThroughputPerformanceStatistics merge(final ThroughputPerformanceStatistics other) { - return new ThroughputPerformanceStatistics(this.collectionStatistics.merge(other.collectionStatistics), totalInvocations + other.totalInvocations, elapsedTotal.plus(other.elapsedTotal)); + return new ThroughputPerformanceStatistics(this.collectionStatistics.merge(other.collectionStatistics), totalInvocations + other.totalInvocations, Duration.ofNanos(elapsedTotal + other.elapsedTotal)); } } diff --git a/src/main/java/com/ethlo/util/IndexedCollection.java b/src/main/java/com/ethlo/util/IndexedCollection.java index 5f893a6..d42918e 100644 --- a/src/main/java/com/ethlo/util/IndexedCollection.java +++ b/src/main/java/com/ethlo/util/IndexedCollection.java @@ -35,4 +35,6 @@ public interface IndexedCollection extends Iterable void sort(); Stream stream(); + + IndexedCollection addAll(Iterable values); } diff --git a/src/main/java/com/ethlo/util/LongList.java b/src/main/java/com/ethlo/util/LongList.java index cee97da..043e494 100644 --- a/src/main/java/com/ethlo/util/LongList.java +++ b/src/main/java/com/ethlo/util/LongList.java @@ -54,6 +54,10 @@ public LongList(int blockSize) @Override public void add(long l) { + if (index == Integer.MAX_VALUE) + { + throw new IndexOutOfBoundsException("Cannot add more than " + Integer.MAX_VALUE + " entries"); + } if (index % blockSize == 0) { blocks.add(new long[blockSize]); @@ -146,4 +150,11 @@ public Stream stream() final Iterable iterable = LongList.this; return StreamSupport.stream(iterable.spliterator(), false); } + + @Override + public IndexedCollection addAll(final Iterable values) + { + values.forEach(this::add); + return this; + } } diff --git a/src/main/java/com/ethlo/util/MathUtil.java b/src/main/java/com/ethlo/util/MathUtil.java deleted file mode 100644 index 39722fa..0000000 --- a/src/main/java/com/ethlo/util/MathUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.ethlo.util; - -/*- - * #%L - * Chronograph - * %% - * Copyright (C) 2019 Morten Haraldsen (ethlo) - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import java.math.BigDecimal; -import java.math.RoundingMode; - -public class MathUtil -{ - private static final BigDecimal TWO = BigDecimal.valueOf(2); - - public static BigDecimal sqrt(BigDecimal value) - { - return sqrt(value, 10); - } - - public static BigDecimal sqrt(BigDecimal value, final int SCALE) - { - if (value.compareTo(BigDecimal.ZERO) == 0) - { - return value; - } - - BigDecimal x0 = BigDecimal.ZERO; - BigDecimal x1 = BigDecimal.valueOf(Math.sqrt(value.doubleValue())); - while (!x0.equals(x1)) - { - x0 = x1; - x1 = value.divide(x0, SCALE, RoundingMode.HALF_UP); - x1 = x1.add(x0); - x1 = x1.divide(TWO, SCALE, RoundingMode.HALF_UP); - } - return x1; - } -} diff --git a/src/test/java/com/ethlo/time/statistics/StatisticsTest.java b/src/test/java/com/ethlo/time/statistics/StatisticsTest.java new file mode 100644 index 0000000..ab4ae5c --- /dev/null +++ b/src/test/java/com/ethlo/time/statistics/StatisticsTest.java @@ -0,0 +1,53 @@ +package com.ethlo.time.statistics; + +/*- + * #%L + * Chronograph + * %% + * Copyright (C) 2019 - 2024 Morten Haraldsen (ethlo) + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.ethlo.util.IndexedCollection; +import com.ethlo.util.IndexedCollectionStatistics; +import com.ethlo.util.LongList; + +class StatisticsTest +{ + private final IndexedCollection list = new LongList().addAll(List.of(200L, 400L, 400L, 400L, 500L, 500L, 700L, 900L)); + private final ThroughputPerformanceStatistics throughputStats = new ThroughputPerformanceStatistics(new IndexedCollectionStatistics(list)); + private final DurationPerformanceStatistics durationStats = new DurationPerformanceStatistics(new IndexedCollectionStatistics(list)); + + @Test + void getAverage() + { + assertThat(throughputStats.getAverage()).isEqualTo(500D); + assertThat(durationStats.getAverage()).isEqualTo(Duration.ofNanos(500)); + } + + @Test + void getStandardDeviation() + { + assertThat(throughputStats.getStandardDeviation()).isEqualTo(200D); + assertThat(durationStats.getStandardDeviation()).isEqualTo(Duration.ofNanos(200)); + } +} diff --git a/src/test/java/com/ethlo/time/statistics/ThroughputPerformanceStatisticsTest.java b/src/test/java/com/ethlo/time/statistics/ThroughputPerformanceStatisticsTest.java deleted file mode 100644 index f804d30..0000000 --- a/src/test/java/com/ethlo/time/statistics/ThroughputPerformanceStatisticsTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.ethlo.time.statistics; - -import com.ethlo.util.IndexedCollection; -import com.ethlo.util.IndexedCollectionStatistics; - -import com.ethlo.util.LongList; - -import org.junit.jupiter.api.Test; - -import java.time.Duration; - -import static org.junit.jupiter.api.Assertions.*; - -class ThroughputPerformanceStatisticsTest -{ - - @Test - void getStandardDeviation() - { - final IndexedCollection list = new LongList(1000); - list.add(123); - final ThroughputPerformanceStatistics stats = new ThroughputPerformanceStatistics(new IndexedCollectionStatistics(list), 5, Duration.ofMillis(456)); - stats.getStandardDeviation(); - } -} \ No newline at end of file diff --git a/src/test/java/com/ethlo/util/LongListTest.java b/src/test/java/com/ethlo/util/LongListTest.java index a49d33b..510e6f0 100644 --- a/src/test/java/com/ethlo/util/LongListTest.java +++ b/src/test/java/com/ethlo/util/LongListTest.java @@ -21,8 +21,9 @@ */ import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; -import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; public class LongListTest @@ -119,14 +120,14 @@ public void percentile() public void getOutOfBounds() { final LongList l = createList(10, false); - Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> l.get(10)); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> l.get(10)); } @Test public void getOutOfBoundsNegative() { final LongList l = createList(10, false); - Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> l.get(-1)); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> l.get(-1)); } @Test @@ -156,9 +157,23 @@ public void iterator() } @Test - public void size() + void size() { final LongList l = createList(10, true); assertThat(l.size()).isEqualTo(10); } + + @Disabled + @Test + void overflow() + { + final LongList l = new LongList(10000); + System.out.println(Runtime.getRuntime().maxMemory() / 1024D / 1024D); + for (long i = 0; i < (long) Integer.MAX_VALUE; i++) + { + l.add(1); + } + + assertThrows(IndexOutOfBoundsException.class, () -> l.add(1)); + } }