diff --git a/examples/example-gradle/build.gradle.kts b/examples/example-gradle/build.gradle.kts index 235e6f0..e485dca 100644 --- a/examples/example-gradle/build.gradle.kts +++ b/examples/example-gradle/build.gradle.kts @@ -8,6 +8,31 @@ version = "1.0-SNAPSHOT" jmh { jmhVersion.set("0.1.0") + + benchmarkMode.set(listOf("avgt")) + timeUnit.set("ns") + warmupIterations.set(2) + warmup.set("1s") + iterations.set(3) + timeOnIteration.set("1s") + fork.set(3) + resultFormat.set("JSON") + + // Force a System.gc() between iterations so heap state is reset before each + // measurement starts. Without this, a GC pause can land inside the measurement + // window and show up as a spurious regression in CI. + forceGC = true + + // Run subset of the benchmarks to avoid long CI runtimes + if (System.getenv("CODSPEED_ENV") != null) { + logger.lifecycle("CODSPEED_ENV detected — running curated CI benchmark subset") + // me.champeau.jmh joins `includes` with commas into a single positional + // regex passed to JMH, so multiple entries collapse to one pattern with + // literal commas and match nothing. Use a single alternation instead. + includes.set(listOf( + ".*(SleepBenchmark|BacktrackingBenchmark|FibBenchmark).*", + )) + } } sourceSets { diff --git a/examples/example-gradle/src/jmh/java/bench/BacktrackingBenchmark.java b/examples/example-gradle/src/jmh/java/bench/BacktrackingBenchmark.java index 5d75754..4602823 100644 --- a/examples/example-gradle/src/jmh/java/bench/BacktrackingBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/BacktrackingBenchmark.java @@ -1,6 +1,7 @@ package bench; import com.thealgorithms.backtracking.*; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; @@ -8,16 +9,13 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class BacktrackingBenchmark { // -- N-Queens -- @State(Scope.Benchmark) public static class NQueensState { - @Param({"4", "5", "6", "7", "8"}) + @Param({"8"}) public int nQueens; } @@ -30,7 +28,7 @@ public List> nQueensSolver(NQueensState state) { @State(Scope.Benchmark) public static class ParenthesesState { - @Param({"3", "4", "5", "6"}) + @Param({"6"}) public int nParens; } @@ -43,34 +41,46 @@ public List generateParentheses(ParenthesesState state) { @State(Scope.Benchmark) public static class CombinationsState { - @Param({"5", "6", "7", "8", "9"}) + @Param({"9"}) public int nCombinations; + + public Integer[] arr; + + @Setup(Level.Trial) + public void setup() { + arr = new Integer[nCombinations]; + for (int i = 0; i < nCombinations; i++) { + arr[i] = i; + } + } } @Benchmark public void generateCombinations(CombinationsState state, Blackhole bh) { - Integer[] arr = new Integer[state.nCombinations]; - for (int i = 0; i < state.nCombinations; i++) { - arr[i] = i; - } - bh.consume(Combination.combination(arr, 3)); + bh.consume(Combination.combination(state.arr, 3)); } // -- Permutations -- @State(Scope.Benchmark) public static class PermutationsState { - @Param({"3", "4", "5", "6", "7"}) + @Param({"7"}) public int nPermutations; + + public Integer[] arr; + + @Setup(Level.Trial) + public void setup() { + arr = new Integer[nPermutations]; + for (int i = 0; i < nPermutations; i++) { + arr[i] = i; + } + } } @Benchmark public void permutations(PermutationsState state, Blackhole bh) { - Integer[] arr = new Integer[state.nPermutations]; - for (int i = 0; i < state.nPermutations; i++) { - arr[i] = i; - } - bh.consume(Permutation.permutation(arr)); + bh.consume(Permutation.permutation(state.arr)); } // -- Sudoku Solver -- @@ -105,16 +115,22 @@ public boolean sudokuSolver(SudokuState state) { @State(Scope.Benchmark) public static class SubsequencesState { - @Param({"8", "10", "12"}) + @Param({"12"}) public int nSubsequences; + + public List seq; + + @Setup(Level.Trial) + public void setup() { + seq = new ArrayList<>(nSubsequences); + for (int i = 0; i < nSubsequences; i++) { + seq.add(i); + } + } } @Benchmark public void generateSubsequences(SubsequencesState state, Blackhole bh) { - List seq = new java.util.ArrayList<>(); - for (int i = 0; i < state.nSubsequences; i++) { - seq.add(i); - } - bh.consume(SubsequenceFinder.generateAll(seq)); + bh.consume(SubsequenceFinder.generateAll(state.seq)); } } diff --git a/examples/example-gradle/src/jmh/java/bench/BitManipulationBenchmark.java b/examples/example-gradle/src/jmh/java/bench/BitManipulationBenchmark.java index fc45b71..7030dc4 100644 --- a/examples/example-gradle/src/jmh/java/bench/BitManipulationBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/BitManipulationBenchmark.java @@ -8,12 +8,9 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class BitManipulationBenchmark { - @Param({"0", "42", "255", "1024", "65535"}) + @Param({"65535"}) private int bitValue; @Benchmark diff --git a/examples/example-gradle/src/jmh/java/bench/DynamicProgrammingBenchmark.java b/examples/example-gradle/src/jmh/java/bench/DynamicProgrammingBenchmark.java index 8f9b704..bda6243 100644 --- a/examples/example-gradle/src/jmh/java/bench/DynamicProgrammingBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/DynamicProgrammingBenchmark.java @@ -6,16 +6,13 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class DynamicProgrammingBenchmark { // -- Fibonacci -- @State(Scope.Benchmark) public static class FibonacciState { - @Param({"10", "20", "30", "40"}) + @Param({"30"}) public int fibN; } @@ -38,7 +35,7 @@ public int fibonacciOptimized(FibonacciState state) { @State(Scope.Benchmark) public static class KnapsackState { - @Param({"10", "15", "20"}) + @Param({"20"}) public int knapsackSize; public int[] knapsackWeights; @@ -64,7 +61,7 @@ public int knapsack(KnapsackState state) { @State(Scope.Benchmark) public static class EditDistanceState { - @Param({"kitten", "saturday"}) + @Param({"saturday"}) public String editWord1; } @@ -77,7 +74,7 @@ public int editDistance(EditDistanceState state) { @State(Scope.Benchmark) public static class LevenshteinState { - @Param({"kitten sitting", "saturday sunday"}) + @Param({"saturday sunday"}) public String levenshteinPair; } @@ -91,7 +88,7 @@ public int levenshteinDistance(LevenshteinState state) { @State(Scope.Benchmark) public static class LisState { - @Param({"10", "50", "100"}) + @Param({"100"}) public int lisSize; public int[] lisArray; @@ -115,7 +112,7 @@ public int longestIncreasingSubsequence(LisState state) { @State(Scope.Benchmark) public static class CoinChangeState { - @Param({"50", "100", "200"}) + @Param({"200"}) public int coinAmount; } @@ -130,7 +127,7 @@ public int coinChange(CoinChangeState state) { @State(Scope.Benchmark) public static class SubsetSumState { - @Param({"10", "15", "20"}) + @Param({"20"}) public int subsetSize; public int[] subsetArr; diff --git a/examples/example-gradle/src/jmh/java/bench/FibBenchmark.java b/examples/example-gradle/src/jmh/java/bench/FibBenchmark.java index 272fed6..2c15ec7 100644 --- a/examples/example-gradle/src/jmh/java/bench/FibBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/FibBenchmark.java @@ -6,9 +6,6 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class FibBenchmark { @Param({"30"}) diff --git a/examples/example-gradle/src/jmh/java/bench/RegexBenchmark.java b/examples/example-gradle/src/jmh/java/bench/RegexBenchmark.java index 3adc366..bf2ec61 100644 --- a/examples/example-gradle/src/jmh/java/bench/RegexBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/RegexBenchmark.java @@ -9,9 +9,6 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class RegexBenchmark { // Complex pattern with alternations, named groups, lookahead, and quantifiers. @@ -26,7 +23,7 @@ public class RegexBenchmark { // Nested quantifiers: (a+)+ applied to a string of 'a's followed by a non-matching char. private static final String BACKTRACK_PATTERN = "^(a+)+b$"; - @Param({"20", "24"}) + @Param({"24"}) private int backtrackLength; private String scanInput; diff --git a/examples/example-gradle/src/jmh/java/bench/RleBenchmark.java b/examples/example-gradle/src/jmh/java/bench/RleBenchmark.java index eb44f38..23fc779 100644 --- a/examples/example-gradle/src/jmh/java/bench/RleBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/RleBenchmark.java @@ -9,12 +9,9 @@ @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.MILLISECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class RleBenchmark { - @Param({"1024", "65536"}) + @Param({"65536"}) private int size; private byte[] rawData; diff --git a/examples/example-gradle/src/jmh/java/bench/SleepBenchmark.java b/examples/example-gradle/src/jmh/java/bench/SleepBenchmark.java index 2a8ef82..a7476b4 100644 --- a/examples/example-gradle/src/jmh/java/bench/SleepBenchmark.java +++ b/examples/example-gradle/src/jmh/java/bench/SleepBenchmark.java @@ -6,9 +6,6 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class SleepBenchmark { private static void busyWait(long nanos) { diff --git a/examples/example-gradle/src/jmh/java/com/thealgorithms/sorts/SortBenchmark.java b/examples/example-gradle/src/jmh/java/com/thealgorithms/sorts/SortBenchmark.java index a942f4a..86ae03d 100644 --- a/examples/example-gradle/src/jmh/java/com/thealgorithms/sorts/SortBenchmark.java +++ b/examples/example-gradle/src/jmh/java/com/thealgorithms/sorts/SortBenchmark.java @@ -1,6 +1,5 @@ package com.thealgorithms.sorts; -import java.util.Arrays; import java.util.Random; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.*; @@ -8,82 +7,51 @@ @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) @State(Scope.Benchmark) -@Warmup(iterations = 1, time = 1) -@Measurement(iterations = 3, time = 1) -@Fork(1) public class SortBenchmark { - @Param({"100", "1000", "10000"}) + @Param({"10000"}) private int size; private Integer[] data; + private Integer[] working; private final QuickSort quickSort = new QuickSort(); private final MergeSort mergeSort = new MergeSort(); - private final HeapSort heapSort = new HeapSort(); - private final InsertionSort insertionSort = new InsertionSort(); - private final BubbleSort bubbleSort = new BubbleSort(); private final TimSort timSort = new TimSort(); - private final ShellSort shellSort = new ShellSort(); - private final SelectionSort selectionSort = new SelectionSort(); private final DualPivotQuickSort dualPivotQuickSort = new DualPivotQuickSort(); - private final IntrospectiveSort introspectiveSort = new IntrospectiveSort(); @Setup(Level.Trial) public void setup() { Random rng = new Random(42); data = new Integer[size]; + working = new Integer[size]; for (int i = 0; i < size; i++) { data[i] = rng.nextInt(size * 10); } } - private Integer[] copyData() { - return Arrays.copyOf(data, data.length); + private Integer[] resetWorking() { + System.arraycopy(data, 0, working, 0, size); + return working; } @Benchmark public Integer[] quickSort() { - return quickSort.sort(copyData()); + return quickSort.sort(resetWorking()); } @Benchmark public Integer[] mergeSort() { - return mergeSort.sort(copyData()); - } - - @Benchmark - public Integer[] heapSort() { - return heapSort.sort(copyData()); + return mergeSort.sort(resetWorking()); } @Benchmark public Integer[] timSort() { - return timSort.sort(copyData()); - } - - @Benchmark - public Integer[] shellSort() { - return shellSort.sort(copyData()); - } - - @Benchmark - public Integer[] selectionSort() { - return selectionSort.sort(copyData()); - } - - @Benchmark - public Integer[] insertionSort() { - return insertionSort.sort(copyData()); + return timSort.sort(resetWorking()); } @Benchmark public Integer[] dualPivotQuickSort() { - return dualPivotQuickSort.sort(copyData()); - } - - @Benchmark - public Integer[] introspectiveSort() { - return introspectiveSort.sort(copyData()); + return dualPivotQuickSort.sort(resetWorking()); } } diff --git a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java index 0b79b79..843fe92 100644 --- a/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java +++ b/jmh-fork/jmh-core/src/main/java/org/openjdk/jmh/runner/Defaults.java @@ -40,7 +40,7 @@ public class Defaults { /** * Number of warmup iterations. */ - public static final int WARMUP_ITERATIONS = 5; + public static final int WARMUP_ITERATIONS = 3; /** * Number of warmup iterations in {@link org.openjdk.jmh.annotations.Mode#SingleShotTime} mode. @@ -55,12 +55,12 @@ public class Defaults { /** * The duration of warmup iterations. */ - public static final TimeValue WARMUP_TIME = TimeValue.seconds(10); + public static final TimeValue WARMUP_TIME = TimeValue.seconds(1); /** * Number of measurement iterations. */ - public static final int MEASUREMENT_ITERATIONS = 5; + public static final int MEASUREMENT_ITERATIONS = 3; /** * Number of measurement iterations in {@link org.openjdk.jmh.annotations.Mode#SingleShotTime} mode. @@ -75,7 +75,7 @@ public class Defaults { /** * The duration of measurement iterations. */ - public static final TimeValue MEASUREMENT_TIME = TimeValue.seconds(10); + public static final TimeValue MEASUREMENT_TIME = TimeValue.seconds(1); /** * Number of measurement threads. @@ -85,7 +85,7 @@ public class Defaults { /** * Number of forks in which we measure the workload. */ - public static final int MEASUREMENT_FORKS = 5; + public static final int MEASUREMENT_FORKS = 3; /** * Number of warmup forks we discard.