mirror of
https://gitlab.uni-marburg.de/langbeid/powersort.git
synced 2025-01-21 19:50:35 +01:00
benchmark: reproducible random lists
This commit is contained in:
parent
e3b90c83cc
commit
025193595c
@ -46,11 +46,15 @@ public class MainJmh {
|
||||
// TODO: This is inaccurate. How to create and use separate arrays for each warmup x iteration x sortAlgorithm ?
|
||||
@Setup(Level.Invocation)
|
||||
public void setup() {
|
||||
// TODO: We tried to store the old `dataEnum` in a separate variable and only call `dataEnum.get()` if `dataEnum` changed. But the separate variable was always reverted to `null`. Why? Maybe as the benchmark method does not use it?
|
||||
// TODO: This leads to different random lists used for each sort impl.
|
||||
//
|
||||
// TODO: This is better anyways: Store random list on disk and reuse it for reproducibility
|
||||
data = dataEnum.get();
|
||||
// A new MainJmh object is created for each @Param variation.
|
||||
// Then, `data` is `null` again.
|
||||
if (data == null) {
|
||||
data = dataEnum.get();
|
||||
}
|
||||
// For all warmup and measurement iterations of one @Param variation, the MainJmh object is reused.
|
||||
// Thus, we can't just sort `data` directly.
|
||||
// Instead, we have to create a copy of it on which the sort algorithm can work.
|
||||
// This way, all iterations sort the same input.
|
||||
workingCopy = data.getCopy();
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,10 @@ public class IntegerArray {
|
||||
private IntegerArray() {
|
||||
}
|
||||
|
||||
public static Integer[] random(final int length) {
|
||||
return random(length, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public static Integer[] random(final int length, final int minInt, final int maxInt) {
|
||||
public static Integer[] random(final int length, final long seed) {
|
||||
final Integer[] list = new Integer[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
list[i] = RandomInt.integer(minInt, maxInt);
|
||||
list[i] = RandomInt.integer(seed);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package de.uni_marburg.powersort.benchmark;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Provides utility methods related to random integers.
|
||||
*/
|
||||
@ -8,15 +10,33 @@ public final class RandomInt {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random integer.
|
||||
*
|
||||
* @return A random integer.
|
||||
*/
|
||||
public static int integer() {
|
||||
return integer(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
public static int integer(final int minInt, final int maxInt) {
|
||||
final double random = Math.random() * (maxInt - minInt) - minInt;
|
||||
return (int) Math.round(random);
|
||||
final double rand01 = Math.random();
|
||||
return helper(minInt, maxInt, rand01);
|
||||
}
|
||||
|
||||
/**
|
||||
* The returned random integer to return is determined by the given seed.
|
||||
*
|
||||
* @return A random integer.
|
||||
*/
|
||||
public static int integer(final long seed) {
|
||||
Random random = new Random(seed);
|
||||
final double rand01 = random.nextDouble();
|
||||
return helper(Integer.MIN_VALUE, Integer.MAX_VALUE, rand01);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rand01 Random value in range [0,1)
|
||||
*/
|
||||
private static int helper(final int minInt, final int maxInt, final double rand01) {
|
||||
final double randMinMax = rand01 * (maxInt - minInt) - minInt;
|
||||
return (int) Math.round(randMinMax);
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,12 @@ public enum DataEnum {
|
||||
DESCENDING_INTEGERS;
|
||||
|
||||
public ObjectSupplier get() {
|
||||
// We use a seed to get the same random list every time -> Repeatable benchmarks on same input data!
|
||||
// final long seed = 3651660232967549736L; // System.nanoTime() ++ Math.random()
|
||||
final long seed = 140506881906827520L; // (long) 'P' * (long) 'O' *(long) 'W' * (long) 'E' * (long) 'R' * (long) 'S' * (long) 'O' * (long) 'R' * (long) 'T';
|
||||
|
||||
return switch (this) {
|
||||
case RANDOM_INTEGERS -> new RandomIntegers();
|
||||
case RANDOM_INTEGERS -> new RandomIntegers(seed);
|
||||
case ASCENDING_INTEGERS -> new AscendingIntegers();
|
||||
case DESCENDING_INTEGERS -> new DescendingIntegers();
|
||||
};
|
||||
|
@ -6,8 +6,8 @@ import de.uni_marburg.powersort.benchmark.LongFormatter;
|
||||
import static de.uni_marburg.powersort.data.DataArraySizes.SIZE_RAND;
|
||||
|
||||
public class RandomIntegers extends IntegerSupplier {
|
||||
public RandomIntegers() {
|
||||
super(IntegerArray.random(SIZE_RAND));
|
||||
public RandomIntegers(final long seed) {
|
||||
super(IntegerArray.random(SIZE_RAND, seed));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,34 +3,46 @@ package de.uni_marburg.powersort.benchmark;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class RandomIntTest {
|
||||
protected RandomIntTest(){
|
||||
// This constructor is intentionally empty. Nothing special is needed here.
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRandomInt() {
|
||||
final double accuracy = 0.99;
|
||||
final int min = (int) Math.round(Integer.MIN_VALUE * accuracy);
|
||||
final int max = (int) Math.round(Integer.MAX_VALUE * accuracy);
|
||||
|
||||
boolean minPassed = false;
|
||||
boolean maxPassed = false;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
final int random = RandomInt.integer();
|
||||
System.out.println(random); //NOPMD - suppressed SystemPrintln - Testing
|
||||
|
||||
if (random <= min) {
|
||||
minPassed = true;
|
||||
}
|
||||
if (random >= max) {
|
||||
maxPassed = true;
|
||||
}
|
||||
if (minPassed && maxPassed) {
|
||||
return;
|
||||
}
|
||||
protected RandomIntTest() {
|
||||
// This constructor is intentionally empty. Nothing special is needed here.
|
||||
}
|
||||
|
||||
Assertions.fail("min or max not reached - not a random int generator");
|
||||
}
|
||||
@Test
|
||||
void testRandomInt() {
|
||||
final double accuracy = 0.99;
|
||||
final int min = (int) Math.round(Integer.MIN_VALUE * accuracy);
|
||||
final int max = (int) Math.round(Integer.MAX_VALUE * accuracy);
|
||||
|
||||
boolean minPassed = false;
|
||||
boolean maxPassed = false;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
final int random = RandomInt.integer();
|
||||
System.out.println(random); //NOPMD - suppressed SystemPrintln - Testing
|
||||
|
||||
if (random <= min) {
|
||||
minPassed = true;
|
||||
}
|
||||
if (random >= max) {
|
||||
maxPassed = true;
|
||||
}
|
||||
if (minPassed && maxPassed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Assertions.fail("min or max not reached - not a random int generator");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReproducibility() {
|
||||
long seed = 1337;
|
||||
|
||||
int expected = 2147483647;
|
||||
long actual = RandomInt.integer(seed);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user