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 ?
|
// TODO: This is inaccurate. How to create and use separate arrays for each warmup x iteration x sortAlgorithm ?
|
||||||
@Setup(Level.Invocation)
|
@Setup(Level.Invocation)
|
||||||
public void setup() {
|
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?
|
// A new MainJmh object is created for each @Param variation.
|
||||||
// TODO: This leads to different random lists used for each sort impl.
|
// Then, `data` is `null` again.
|
||||||
//
|
if (data == null) {
|
||||||
// TODO: This is better anyways: Store random list on disk and reuse it for reproducibility
|
data = dataEnum.get();
|
||||||
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();
|
workingCopy = data.getCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,10 @@ public class IntegerArray {
|
|||||||
private IntegerArray() {
|
private IntegerArray() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer[] random(final int length) {
|
public static Integer[] random(final int length, final long seed) {
|
||||||
return random(length, Integer.MIN_VALUE, Integer.MAX_VALUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Integer[] random(final int length, final int minInt, final int maxInt) {
|
|
||||||
final Integer[] list = new Integer[length];
|
final Integer[] list = new Integer[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
list[i] = RandomInt.integer(minInt, maxInt);
|
list[i] = RandomInt.integer(seed);
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package de.uni_marburg.powersort.benchmark;
|
package de.uni_marburg.powersort.benchmark;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides utility methods related to random integers.
|
* Provides utility methods related to random integers.
|
||||||
*/
|
*/
|
||||||
@ -8,15 +10,33 @@ public final class RandomInt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random integer.
|
|
||||||
*
|
|
||||||
* @return A random integer.
|
* @return A random integer.
|
||||||
*/
|
*/
|
||||||
public static int integer() {
|
public static int integer() {
|
||||||
return integer(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
return integer(Integer.MIN_VALUE, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
public static int integer(final int minInt, final int maxInt) {
|
public static int integer(final int minInt, final int maxInt) {
|
||||||
final double random = Math.random() * (maxInt - minInt) - minInt;
|
final double rand01 = Math.random();
|
||||||
return (int) Math.round(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;
|
DESCENDING_INTEGERS;
|
||||||
|
|
||||||
public ObjectSupplier get() {
|
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) {
|
return switch (this) {
|
||||||
case RANDOM_INTEGERS -> new RandomIntegers();
|
case RANDOM_INTEGERS -> new RandomIntegers(seed);
|
||||||
case ASCENDING_INTEGERS -> new AscendingIntegers();
|
case ASCENDING_INTEGERS -> new AscendingIntegers();
|
||||||
case DESCENDING_INTEGERS -> new DescendingIntegers();
|
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;
|
import static de.uni_marburg.powersort.data.DataArraySizes.SIZE_RAND;
|
||||||
|
|
||||||
public class RandomIntegers extends IntegerSupplier {
|
public class RandomIntegers extends IntegerSupplier {
|
||||||
public RandomIntegers() {
|
public RandomIntegers(final long seed) {
|
||||||
super(IntegerArray.random(SIZE_RAND));
|
super(IntegerArray.random(SIZE_RAND, seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3,34 +3,46 @@ package de.uni_marburg.powersort.benchmark;
|
|||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
class RandomIntTest {
|
class RandomIntTest {
|
||||||
protected RandomIntTest(){
|
protected RandomIntTest() {
|
||||||
// This constructor is intentionally empty. Nothing special is needed here.
|
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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