Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use threadlocal random generator to avoid contention #399

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class AuctionMarkBenchmark extends BenchmarkModule {
private static final Logger LOG = LoggerFactory.getLogger(AuctionMarkBenchmark.class);


private final RandomGenerator rng = new RandomGenerator((int) System.currentTimeMillis());
private final RandomGenerator rng = new RandomGenerator();

public AuctionMarkBenchmark(WorkloadConfiguration workConf) {
super(workConf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
import java.util.concurrent.CountDownLatch;

public class CHBenCHmarkLoader extends Loader<CHBenCHmark> {
private static final RandomGenerator ran = new RandomGenerator(0);
private static final RandomGenerator ran = new RandomGenerator();


//create possible keys for n_nationkey ([a-zA-Z0-9])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

public class SEATSBenchmark extends BenchmarkModule {

private final RandomGenerator rng = new RandomGenerator((int) System.currentTimeMillis());
private final RandomGenerator rng = new RandomGenerator();

public SEATSBenchmark(WorkloadConfiguration workConf) {
super(workConf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static Customer newCustomerFromResults(ResultSet rs)
return c;
}

private static final RandomGenerator ran = new RandomGenerator(0);
private static final RandomGenerator ran = new RandomGenerator();

public static String randomStr(int strLen) {
if (strLen > 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class TPCHWorker extends Worker<TPCHBenchmark> {
public TPCHWorker(TPCHBenchmark benchmarkModule, int id) {
super(benchmarkModule, id);
this.rng().setSeed(15721);
rand = new RandomGenerator(this.rng().nextInt());
rand = new RandomGenerator();
}

@Override
Expand Down
253 changes: 145 additions & 108 deletions src/main/java/com/oltpbenchmark/util/RandomGenerator.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020 by OLTPBenchmark Project
* Copyright 2023 by OLTPBenchmark Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,110 +16,147 @@
*/


package com.oltpbenchmark.util;

import java.util.Random;

public class RandomGenerator extends Random {

/**
* Constructor
*
* @param seed
*/
public RandomGenerator(int seed) {
super(seed);
}

/**
* Returns a random int value between minimum and maximum (inclusive)
*
* @param minimum
* @param maximum
* @returns a int in the range [minimum, maximum]. Note that this is inclusive.
*/
public int number(int minimum, int maximum) {

int range_size = maximum - minimum + 1;
int value = this.nextInt(range_size);
value += minimum;

return value;
}

/**
* Returns a random long value between minimum and maximum (inclusive)
*
* @param minimum
* @param maximum
* @return
*/
public long number(long minimum, long maximum) {

long range_size = (maximum - minimum) + 1;

// error checking and 2^x checking removed for simplicity.
long bits, val;
do {
bits = (this.nextLong() << 1) >>> 1;
val = bits % range_size;
}
while (bits - val + range_size < 0L);
val += minimum;


return val;
}

/**
* @param decimal_places
* @param minimum
* @param maximum
* @return
*/
public double fixedPoint(int decimal_places, double minimum, double maximum) {


int multiplier = 1;
for (int i = 0; i < decimal_places; ++i) {
multiplier *= 10;
}

int int_min = (int) (minimum * multiplier + 0.5);
int int_max = (int) (maximum * multiplier + 0.5);

return (double) this.number(int_min, int_max) / (double) multiplier;
}

/**
* @returns a random alphabetic string with length in range [minimum_length, maximum_length].
*/
public String astring(int minimum_length, int maximum_length) {
return randomString(minimum_length, maximum_length, 'a', 26);
}


/**
* @returns a random numeric string with length in range [minimum_length, maximum_length].
*/
public String nstring(int minimum_length, int maximum_length) {
return randomString(minimum_length, maximum_length, '0', 10);
}

/**
* @param minimum_length
* @param maximum_length
* @param base
* @param numCharacters
* @return
*/
private String randomString(int minimum_length, int maximum_length, char base, int numCharacters) {
int length = number(minimum_length, maximum_length);
byte baseByte = (byte) base;
byte[] bytes = new byte[length];
for (int i = 0; i < length; ++i) {
bytes[i] = (byte) (baseByte + number(0, numCharacters - 1));
}
return new String(bytes);
}
}
package com.oltpbenchmark.util;

import java.util.concurrent.ThreadLocalRandom;

public class RandomGenerator extends java.util.Random {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it still produce the same results as the previous version? Any tests for that?


/**
* Constructor
*/
public RandomGenerator() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version drops the seed from the constructor. This could be very useful for implementing more reproducible benchmarking results. Not claiming that benchbase does a great job of carrying that thru all levels of the stack now, but this seems to introduce further issues with that.

}

@Override
protected int next(int bits) {
return ThreadLocalRandom.current().nextInt() >>> (32 - bits);
}

@Override
public int nextInt() {
return ThreadLocalRandom.current().nextInt();
}

@Override
public int nextInt(int bound) {
return ThreadLocalRandom.current().nextInt(bound);
}

@Override
public long nextLong() {
return ThreadLocalRandom.current().nextLong();
}

@Override
public boolean nextBoolean() {
return ThreadLocalRandom.current().nextBoolean();
}

@Override
public float nextFloat() {
return ThreadLocalRandom.current().nextFloat();
}

@Override
public double nextDouble() {
return ThreadLocalRandom.current().nextDouble();
}

@Override
public double nextGaussian() {
return ThreadLocalRandom.current().nextGaussian();
}

/**
* Returns a random int value between minimum and maximum (inclusive)
*
* @param minimum
* @param maximum
* @returns a int in the range [minimum, maximum]. Note that this is inclusive.
*/
public int number(int minimum, int maximum) {

int range_size = maximum - minimum + 1;
int value = ThreadLocalRandom.current().nextInt(range_size);
value += minimum;

return value;
}

/**
* Returns a random long value between minimum and maximum (inclusive)
*
* @param minimum
* @param maximum
* @return
*/
public long number(long minimum, long maximum) {

long range_size = (maximum - minimum) + 1;

// error checking and 2^x checking removed for simplicity.
long bits, val;
do {
bits = (ThreadLocalRandom.current().nextLong() << 1) >>> 1;
val = bits % range_size;
}
while (bits - val + range_size < 0L);
val += minimum;


return val;
}

/**
* @param decimal_places
* @param minimum
* @param maximum
* @return
*/
public double fixedPoint(int decimal_places, double minimum, double maximum) {


int multiplier = 1;
for (int i = 0; i < decimal_places; ++i) {
multiplier *= 10;
}

int int_min = (int) (minimum * multiplier + 0.5);
int int_max = (int) (maximum * multiplier + 0.5);

return (double) this.number(int_min, int_max) / (double) multiplier;
}

/**
* @returns a random alphabetic string with length in range [minimum_length, maximum_length].
*/
public String astring(int minimum_length, int maximum_length) {
return randomString(minimum_length, maximum_length, 'a', 26);
}


/**
* @returns a random numeric string with length in range [minimum_length, maximum_length].
*/
public String nstring(int minimum_length, int maximum_length) {
return randomString(minimum_length, maximum_length, '0', 10);
}

/**
* @param minimum_length
* @param maximum_length
* @param base
* @param numCharacters
* @return
*/
private String randomString(int minimum_length, int maximum_length, char base, int numCharacters) {
int length = number(minimum_length, maximum_length);
byte baseByte = (byte) base;
byte[] bytes = new byte[length];
for (int i = 0; i < length; ++i) {
bytes[i] = (byte) (baseByte + number(0, numCharacters - 1));
}
return new String(bytes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void testSaveLoadProfile() throws Exception {
assertNotNull(orig);
assertFalse(orig.users_per_itemCount.isEmpty());

AuctionMarkProfile copy = new AuctionMarkProfile(this.benchmark, new RandomGenerator(0));
AuctionMarkProfile copy = new AuctionMarkProfile(this.benchmark, new RandomGenerator());
assertTrue(copy.users_per_itemCount.isEmpty());

List<Worker<?>> workers = this.benchmark.makeWorkers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class TestUserIdGenerator {

private static final int NUM_CLIENTS = 10;
private static final int NUM_USERS = 1000;
private static final RandomGenerator rand = new RandomGenerator(0); // (int)System.currentTimeMillis());
private static final RandomGenerator rand = new RandomGenerator();

private static final Zipf randomNumItems = new Zipf(rand,
AuctionMarkConstants.ITEM_ITEMS_PER_SELLER_MIN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public void testGetFirst() {
@Test
public void testPop() {
String[] expected = new String[11];
RandomGenerator rng = new RandomGenerator(0);
RandomGenerator rng = new RandomGenerator();
for (int i = 0; i < expected.length; i++) {
expected[i] = rng.astring(1, 32);
} // FOR
Expand Down