diff --git a/core/src/main/java/com/yahoo/ycsb/BasicDB.java b/core/src/main/java/com/yahoo/ycsb/BasicDB.java index 15d1101053c27ffd7228c21ff881fb44a77230de..3972da6979d42280e98879dd95a8c03892549f34 100644 --- a/core/src/main/java/com/yahoo/ycsb/BasicDB.java +++ b/core/src/main/java/com/yahoo/ycsb/BasicDB.java @@ -20,6 +20,7 @@ package com.yahoo.ycsb; import java.util.*; import java.util.Map.Entry; import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; @@ -60,7 +61,7 @@ public class BasicDB extends DB { if (todelay > 0) { long delayNs; if (randomizedelay) { - delayNs = TimeUnit.MILLISECONDS.toNanos(Utils.random().nextInt(todelay)); + delayNs = TimeUnit.MILLISECONDS.toNanos(ThreadLocalRandom.current().nextInt(todelay)); if (delayNs == 0) { return; } diff --git a/core/src/main/java/com/yahoo/ycsb/Client.java b/core/src/main/java/com/yahoo/ycsb/Client.java index 1e31c11210b2d210b9f691750a1aba9784590944..e8b70600f372af95699bb400053c869e1459dfbf 100644 --- a/core/src/main/java/com/yahoo/ycsb/Client.java +++ b/core/src/main/java/com/yahoo/ycsb/Client.java @@ -33,6 +33,7 @@ import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; @@ -442,7 +443,7 @@ class ClientThread implements Runnable { // GH issue 4 - throws exception if _target>1 because random.nextInt argument must be >0 // and the sleep() doesn't make sense for granularities < 1 ms anyway if ((targetOpsPerMs > 0) && (targetOpsPerMs <= 1.0)) { - long randomMinorDelay = Utils.random().nextInt((int) targetOpsTickNs); + long randomMinorDelay = ThreadLocalRandom.current().nextInt((int) targetOpsTickNs); sleepUntil(System.nanoTime() + randomMinorDelay); } try { diff --git a/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java b/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java index 1cbf3a5d0fc12ffb59071adbd3c9dd94a79a4adc..384e13873f793daee1cdc0d77f6a23b6ce9111a9 100644 --- a/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java +++ b/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.Vector; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReadWriteLock; @@ -43,7 +44,7 @@ public class GoodBadUglyDB extends DB { } private void delay() { - final Random random = Utils.random(); + final Random random = ThreadLocalRandom.current(); double p = random.nextDouble(); int mod; if (p < 0.9) { diff --git a/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java b/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java index 681224e8fbb5677c70a948982606b6ae0b541c46..e21689cce26770668314b4f72ab8b53d8365724f 100644 --- a/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java +++ b/core/src/main/java/com/yahoo/ycsb/RandomByteIterator.java @@ -16,6 +16,8 @@ */ package com.yahoo.ycsb; +import java.util.concurrent.ThreadLocalRandom; + /** * A ByteIterator that generates a random sequence of bytes. */ @@ -31,7 +33,7 @@ public class RandomByteIterator extends ByteIterator { } private void fillBytesImpl(byte[] buffer, int base) { - int bytes = Utils.random().nextInt(); + int bytes = ThreadLocalRandom.current().nextInt(); switch (buffer.length - base) { default: diff --git a/core/src/main/java/com/yahoo/ycsb/Utils.java b/core/src/main/java/com/yahoo/ycsb/Utils.java index ade6a1cee3956e134bf14985b68d005a01d9bac4..9fdf079e77128f0a2489aac26dc5eee78ec2bace 100644 --- a/core/src/main/java/com/yahoo/ycsb/Utils.java +++ b/core/src/main/java/com/yahoo/ycsb/Utils.java @@ -23,7 +23,7 @@ import java.lang.management.OperatingSystemMXBean; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; /** * Utility functions. @@ -33,18 +33,6 @@ public final class Utils { // not used } - private static final Random RAND = new Random(); - private static final ThreadLocal<Random> RNG = new ThreadLocal<Random>(); - - public static Random random() { - Random ret = RNG.get(); - if (ret == null) { - ret = new Random(RAND.nextLong()); - RNG.set(ret); - } - return ret; - } - /** * Hash an integer value. */ @@ -234,7 +222,7 @@ public final class Utils { */ public static <T> T [] shuffleArray(final T[] array) { for (int i = array.length -1; i > 0; i--) { - final int idx = RAND.nextInt(i + 1); + final int idx = ThreadLocalRandom.current().nextInt(i + 1); final T temp = array[idx]; array[idx] = array[i]; array[i] = temp; diff --git a/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java index fa7caf4bd0fc7c5be73ba75eb4e7713924b73964..c445f055a4d81cdfdd6b26bbca0cdf6d26add411 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java @@ -17,10 +17,9 @@ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; - import java.util.ArrayList; import java.util.Collection; +import java.util.concurrent.ThreadLocalRandom; import static java.util.Objects.requireNonNull; @@ -56,7 +55,7 @@ public class DiscreteGenerator extends Generator<String> { sum += p.weight; } - double val = Utils.random().nextDouble(); + double val = ThreadLocalRandom.current().nextDouble(); for (Pair p : values) { double pw = p.weight / sum; diff --git a/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java index 4ff7296ad9b457daa674baa5ece384cda6beb9c1..cb3247c774cb8497894384e9ef7d5a38874de6b7 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java @@ -17,7 +17,7 @@ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; +import java.util.concurrent.ThreadLocalRandom; /** * A generator of an exponential distribution. It produces a sequence @@ -66,7 +66,7 @@ public class ExponentialGenerator extends NumberGenerator { */ @Override public Double nextValue() { - return -Math.log(Utils.random().nextDouble()) / gamma; + return -Math.log(ThreadLocalRandom.current().nextDouble()) / gamma; } @Override diff --git a/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java index 766de44cc27eaebb0cda51786f4c27e55144f43e..f5dc0b332a75da47c50cbec37ed7952bf89b9455 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java @@ -16,12 +16,11 @@ */ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; - import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; +import java.util.concurrent.ThreadLocalRandom; /** * Generate integers according to a histogram distribution. The histogram @@ -89,7 +88,7 @@ public class HistogramGenerator extends NumberGenerator { @Override public Long nextValue() { - int number = Utils.random().nextInt((int) area); + int number = ThreadLocalRandom.current().nextInt((int) area); int i; for (i = 0; i < (buckets.length - 1); i++) { diff --git a/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java index 677ebd2f2bbafe7e10145ed9085d1f5ca15effcf..73a9882da4b2b19747f79c1874e27dc21315698d 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java @@ -16,9 +16,8 @@ */ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; - import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; /** * Generate integers resembling a hotspot distribution where x% of operations @@ -75,13 +74,13 @@ public class HotspotIntegerGenerator extends NumberGenerator { @Override public Long nextValue() { long value = 0; - Random random = Utils.random(); + Random random = ThreadLocalRandom.current(); if (random.nextDouble() < hotOpnFraction) { // Choose a value from the hot set. - value = lowerBound + Math.abs(Utils.random().nextLong()) % hotInterval; + value = lowerBound + Math.abs(random.nextLong()) % hotInterval; } else { // Choose a value from the cold set. - value = lowerBound + hotInterval + Math.abs(Utils.random().nextLong()) % coldInterval; + value = lowerBound + hotInterval + Math.abs(random.nextLong()) % coldInterval; } setLastValue(value); return value; diff --git a/core/src/main/java/com/yahoo/ycsb/generator/UniformLongGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/UniformLongGenerator.java index 2d1994f957d110ffaa1c536ca3ba8d0cfd216241..f042284d42df68e38c278466fd60a4df3ba15497 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/UniformLongGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/UniformLongGenerator.java @@ -17,7 +17,7 @@ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; +import java.util.concurrent.ThreadLocalRandom; /** * Generates longs randomly uniform from an interval. @@ -41,7 +41,7 @@ public class UniformLongGenerator extends NumberGenerator { @Override public Long nextValue() { - long ret = Math.abs(Utils.random().nextLong()) % interval + lb; + long ret = Math.abs(ThreadLocalRandom.current().nextLong()) % interval + lb; setLastValue(ret); return ret; diff --git a/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java index a6514edad937f9ff404e9a309291daa2a286158c..bf13e87006788ece0111794b1f958988b5682846 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java @@ -17,7 +17,7 @@ package com.yahoo.ycsb.generator; -import com.yahoo.ycsb.Utils; +import java.util.concurrent.ThreadLocalRandom; /** * A generator of a zipfian distribution. It produces a sequence of items, such that some items are more popular than @@ -247,7 +247,7 @@ public class ZipfianGenerator extends NumberGenerator { } } - double u = Utils.random().nextDouble(); + double u = ThreadLocalRandom.current().nextDouble(); double uz = u * zetan; if (uz < 1.0) { diff --git a/core/src/main/java/com/yahoo/ycsb/workloads/TimeSeriesWorkload.java b/core/src/main/java/com/yahoo/ycsb/workloads/TimeSeriesWorkload.java index 5d0eabd0f0115d2be41999a72f1a971f418659a4..be97b206b028f2d856d19c3e5cee4f2870c0300f 100644 --- a/core/src/main/java/com/yahoo/ycsb/workloads/TimeSeriesWorkload.java +++ b/core/src/main/java/com/yahoo/ycsb/workloads/TimeSeriesWorkload.java @@ -21,9 +21,11 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; +import java.util.Random; import java.util.Set; import java.util.TreeMap; import java.util.Vector; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import com.yahoo.ycsb.ByteIterator; @@ -731,9 +733,9 @@ public class TimeSeriesWorkload extends Workload { protected void doTransactionRead(final DB db, Object threadstate) { final ThreadState state = (ThreadState) threadstate; final String keyname = keys[keychooser.nextValue().intValue()]; - + final Random random = ThreadLocalRandom.current(); int offsets = state.queryOffsetGenerator.nextValue().intValue(); - //int offsets = Utils.random().nextInt(maxOffsets - 1); + //int offsets = random.nextInt(maxOffsets - 1); final long startTimestamp; if (offsets > 0) { startTimestamp = state.startTimestamp + state.timestampGenerator.getOffset(offsets); @@ -748,14 +750,14 @@ public class TimeSeriesWorkload extends Workload { fields.add(tagKeys[i]); } else { fields.add(tagKeys[i] + tagPairDelimiter + - tagValues[Utils.random().nextInt(tagCardinality[i])]); + tagValues[random.nextInt(tagCardinality[i])]); } } if (queryTimeSpan > 0) { final long endTimestamp; if (queryRandomTimeSpan) { - endTimestamp = startTimestamp + (timestampInterval * Utils.random().nextInt(queryTimeSpan / timestampInterval)); + endTimestamp = startTimestamp + (timestampInterval * random.nextInt(queryTimeSpan / timestampInterval)); } else { endTimestamp = startTimestamp + queryTimeSpan; } @@ -793,13 +795,13 @@ public class TimeSeriesWorkload extends Workload { protected void doTransactionScan(final DB db, Object threadstate) { final ThreadState state = (ThreadState) threadstate; - - final String keyname = keys[Utils.random().nextInt(keys.length)]; + final Random random = ThreadLocalRandom.current(); + final String keyname = keys[random.nextInt(keys.length)]; // choose a random scan length int len = scanlength.nextValue().intValue(); - int offsets = Utils.random().nextInt(maxOffsets - 1); + int offsets = random.nextInt(maxOffsets - 1); final long startTimestamp; if (offsets > 0) { startTimestamp = state.startTimestamp + state.timestampGenerator.getOffset(offsets); @@ -814,14 +816,14 @@ public class TimeSeriesWorkload extends Workload { fields.add(tagKeys[i]); } else { fields.add(tagKeys[i] + tagPairDelimiter + - tagValues[Utils.random().nextInt(tagCardinality[i])]); + tagValues[random.nextInt(tagCardinality[i])]); } } if (queryTimeSpan > 0) { final long endTimestamp; if (queryRandomTimeSpan) { - endTimestamp = startTimestamp + (timestampInterval * Utils.random().nextInt(queryTimeSpan / timestampInterval)); + endTimestamp = startTimestamp + (timestampInterval * random.nextInt(queryTimeSpan / timestampInterval)); } else { endTimestamp = startTimestamp + queryTimeSpan; } @@ -842,10 +844,10 @@ public class TimeSeriesWorkload extends Workload { protected void doTransactionDelete(final DB db, Object threadstate) { final ThreadState state = (ThreadState) threadstate; + final Random random = ThreadLocalRandom.current(); + final StringBuilder buf = new StringBuilder().append(keys[random.nextInt(keys.length)]); - final StringBuilder buf = new StringBuilder().append(keys[Utils.random().nextInt(keys.length)]); - - int offsets = Utils.random().nextInt(maxOffsets - 1); + int offsets = random.nextInt(maxOffsets - 1); final long startTimestamp; if (offsets > 0) { startTimestamp = state.startTimestamp + state.timestampGenerator.getOffset(offsets); @@ -860,14 +862,14 @@ public class TimeSeriesWorkload extends Workload { .append(tagKeys[i]); } else { buf.append(deleteDelimiter).append(tagKeys[i] + tagPairDelimiter + - tagValues[Utils.random().nextInt(tagCardinality[i])]); + tagValues[random.nextInt(tagCardinality[i])]); } } if (queryTimeSpan > 0) { final long endTimestamp; if (queryRandomTimeSpan) { - endTimestamp = startTimestamp + (timestampInterval * Utils.random().nextInt(queryTimeSpan / timestampInterval)); + endTimestamp = startTimestamp + (timestampInterval * random.nextInt(queryTimeSpan / timestampInterval)); } else { endTimestamp = startTimestamp + queryTimeSpan; } @@ -1168,8 +1170,8 @@ public class TimeSeriesWorkload extends Workload { * @return The next key to write. */ protected String nextDataPoint(final Map<String, ByteIterator> map, final boolean isInsert) { - int iterations = sparsity <= 0 ? 1 : - Utils.random().nextInt((int) ((double) perKeyCardinality * sparsity)); + final Random random = ThreadLocalRandom.current(); + int iterations = sparsity <= 0 ? 1 : random.nextInt((int) ((double) perKeyCardinality * sparsity)); if (iterations < 1) { iterations = 1; } @@ -1202,7 +1204,7 @@ public class TimeSeriesWorkload extends Workload { if (!isInsert) { final long delta = (timestampGenerator.currentValue() - startTimestamp) / timestampInterval; - final int intervals = Utils.random().nextInt((int) delta); + final int intervals = random.nextInt((int) delta); map.put(timestampKey, new NumericByteIterator(startTimestamp + (intervals * timestampInterval))); } else if (delayedSeries > 0) { // See if the series falls in a delay bucket and calculate an offset earlier @@ -1228,18 +1230,16 @@ public class TimeSeriesWorkload extends Workload { } else { switch (valueType) { case INTEGERS: - map.put(valueKey, new NumericByteIterator(Utils.random().nextInt())); + map.put(valueKey, new NumericByteIterator(random.nextInt())); break; case FLOATS: - map.put(valueKey, new NumericByteIterator( - Utils.random().nextDouble() * (double) 100000)); + map.put(valueKey, new NumericByteIterator(random.nextDouble() * (double) 100000)); break; case MIXED: - if (Utils.random().nextBoolean()) { - map.put(valueKey, new NumericByteIterator(Utils.random().nextInt())); + if (random.nextBoolean()) { + map.put(valueKey, new NumericByteIterator(random.nextInt())); } else { - map.put(valueKey, new NumericByteIterator( - Utils.random().nextDouble() * (double) 100000)); + map.put(valueKey, new NumericByteIterator(random.nextDouble() * (double) 100000)); } break; default: