From 0a330744c5b6f3b1a49e8988ccf1f6ac748340f5 Mon Sep 17 00:00:00 2001 From: Vitaliy Funshteyn <vfunshteyn@applelg.net> Date: Fri, 18 Dec 2015 17:27:03 -0800 Subject: [PATCH] [core] Refactored generators --- .../AcknowledgedCounterGenerator.java | 2 +- .../generator/ConstantIntegerGenerator.java | 4 +- .../ycsb/generator/CounterGenerator.java | 21 ++--- .../ycsb/generator/DiscreteGenerator.java | 51 +++++------- .../ycsb/generator/ExponentialGenerator.java | 35 +++----- .../yahoo/ycsb/generator/FileGenerator.java | 53 +++++------- .../com/yahoo/ycsb/generator/Generator.java | 26 ++++-- .../ycsb/generator/HistogramGenerator.java | 81 +++++++++---------- .../generator/HotspotIntegerGenerator.java | 6 +- ...gerGenerator.java => NumberGenerator.java} | 46 +++-------- .../generator/ScrambledZipfianGenerator.java | 25 +++--- .../ycsb/generator/SkewedLatestGenerator.java | 21 ++--- .../ycsb/generator/UniformGenerator.java | 29 ++++--- .../generator/UniformIntegerGenerator.java | 12 ++- .../ycsb/generator/ZipfianGenerator.java | 44 +++------- .../workloads/ConstantOccupancyWorkload.java | 13 ++- .../yahoo/ycsb/workloads/CoreWorkload.java | 78 +++++++++--------- .../AcknowledgedCounterGeneratorTest.java | 2 +- .../ycsb/generator/TestZipfianGenerator.java | 2 +- .../exporter/TestMeasurementsExporter.java | 2 +- 20 files changed, 234 insertions(+), 319 deletions(-) rename core/src/main/java/com/yahoo/ycsb/generator/{IntegerGenerator.java => NumberGenerator.java} (67%) diff --git a/core/src/main/java/com/yahoo/ycsb/generator/AcknowledgedCounterGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/AcknowledgedCounterGenerator.java index 69884c29..3015c51a 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/AcknowledgedCounterGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/AcknowledgedCounterGenerator.java @@ -50,7 +50,7 @@ public class AcknowledgedCounterGenerator extends CounterGenerator * (as opposed to the highest generated counter value). */ @Override - public int lastInt() + public Integer lastValue() { return limit; } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/ConstantIntegerGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/ConstantIntegerGenerator.java index 94dd3a6a..f3a634d6 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ConstantIntegerGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ConstantIntegerGenerator.java @@ -22,7 +22,7 @@ package com.yahoo.ycsb.generator; * @author sears * */ -public class ConstantIntegerGenerator extends IntegerGenerator { +public class ConstantIntegerGenerator extends NumberGenerator { private final int i; /** * @param i The integer that this generator will always return. @@ -32,7 +32,7 @@ public class ConstantIntegerGenerator extends IntegerGenerator { } @Override - public int nextInt() { + public Integer nextValue() { return i; } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/CounterGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/CounterGenerator.java index df37b239..7ba7382d 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/CounterGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/CounterGenerator.java @@ -22,9 +22,9 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Generates a sequence of integers 0, 1, ... */ -public class CounterGenerator extends IntegerGenerator +public class CounterGenerator extends NumberGenerator { - final AtomicInteger counter; + private final AtomicInteger counter; /** * Create a counter that starts at countstart @@ -32,23 +32,18 @@ public class CounterGenerator extends IntegerGenerator public CounterGenerator(int countstart) { counter=new AtomicInteger(countstart); - setLastInt(counter.get()-1); } - /** - * If the generator returns numeric (integer) values, return the next value as an int. Default is to return -1, which - * is appropriate for generators that do not return numeric values. - */ - public int nextInt() + @Override + public Integer nextValue() { - int ret = counter.getAndIncrement(); - setLastInt(ret); - return ret; + return counter.getAndIncrement(); } + @Override - public int lastInt() + public Integer lastValue() { - return counter.get() - 1; + return counter.get() - 1; } @Override public double mean() { 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 c28f3ae7..398c44c1 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/DiscreteGenerator.java @@ -17,42 +17,42 @@ package com.yahoo.ycsb.generator; -import java.util.Vector; -import java.util.Random; +import java.util.ArrayList; +import java.util.Collection; +import static java.util.Objects.requireNonNull; import com.yahoo.ycsb.Utils; -import com.yahoo.ycsb.WorkloadException; /** * Generates a distribution by choosing from a discrete set of values. */ -public class DiscreteGenerator extends Generator +public class DiscreteGenerator extends Generator<String> { - class Pair + private static class Pair { - public double _weight; - public String _value; + private double _weight; + private String _value; Pair(double weight, String value) { _weight=weight; - _value=value; + _value = requireNonNull(value); } } - Vector<Pair> _values; - String _lastvalue; + private final Collection<Pair> _values = new ArrayList<>(); + private String _lastvalue; public DiscreteGenerator() { - _values=new Vector<Pair>(); _lastvalue=null; } /** * Generate the next string in the distribution. */ - public String nextString() + @Override + public String nextValue() { double sum=0; @@ -65,31 +65,17 @@ public class DiscreteGenerator extends Generator for (Pair p : _values) { - if (val<p._weight/sum) + double pw = p._weight / sum; + if (val < pw) { return p._value; } - val-=p._weight/sum; + val -= pw; } - //should never get here. - System.out.println("oops. should not get here."); + throw new AssertionError("oops. should not get here."); - System.exit(0); - - return null; - } - - /** - * If the generator returns numeric (integer) values, return the next value as an int. Default is to return -1, which - * is appropriate for generators that do not return numeric values. - * - * @throws WorkloadException if this generator does not support integer values - */ - public int nextInt() throws WorkloadException - { - throw new WorkloadException("DiscreteGenerator does not support nextInt()"); } /** @@ -97,11 +83,12 @@ public class DiscreteGenerator extends Generator * Calling lastString() should not advance the distribution or have any side effects. If nextString() has not yet * been called, lastString() should return something reasonable. */ - public String lastString() + @Override + public String lastValue() { if (_lastvalue==null) { - _lastvalue=nextString(); + _lastvalue=nextValue(); } return _lastvalue; } 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 de1a2760..03318edc 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ExponentialGenerator.java @@ -17,20 +17,18 @@ package com.yahoo.ycsb.generator; -import java.util.Random; - import com.yahoo.ycsb.Utils; /** * A generator of an exponential distribution. It produces a sequence - * of time intervals (integers) according to an exponential + * of time intervals according to an exponential * distribution. Smaller intervals are more frequent than larger * ones, and there is no bound on the length of an interval. When you * construct an instance of this class, you specify a parameter gamma, * which corresponds to the rate at which events occur. * Alternatively, 1/gamma is the average length of an interval. */ -public class ExponentialGenerator extends IntegerGenerator +public class ExponentialGenerator extends NumberGenerator { // What percentage of the readings should be within the most recent exponential.frac portion of the dataset? public static final String EXPONENTIAL_PERCENTILE_PROPERTY="exponential.percentile"; @@ -43,7 +41,7 @@ public class ExponentialGenerator extends IntegerGenerator /** * The exponential constant to use. */ - double _gamma; + private double _gamma; /******************************* Constructors **************************************/ @@ -62,27 +60,16 @@ public class ExponentialGenerator extends IntegerGenerator /****************************************************************************************/ - /** - * Generate the next item. this distribution will be skewed toward lower integers; e.g. 0 will - * be the most popular, 1 the next most popular, etc. - * @param itemcount The number of items in the distribution. - * @return The next item in the sequence. - */ - @Override - public int nextInt() - { - return (int)nextLong(); - } /** - * Generate the next item as a long. - * - * @param itemcount The number of items in the distribution. - * @return The next item in the sequence. - */ - public long nextLong() + * Generate the next item as a long. This distribution will be skewed toward lower values; e.g. 0 will + * be the most popular, 1 the next most popular, etc. + * @return The next item in the sequence. + */ + @Override + public Double nextValue() { - return (long) (-Math.log(Utils.random().nextDouble()) / _gamma); + return -Math.log(Utils.random().nextDouble()) / _gamma; } @Override @@ -93,7 +80,7 @@ public class ExponentialGenerator extends IntegerGenerator ExponentialGenerator e = new ExponentialGenerator(90, 100); int j = 0; for(int i = 0; i < 1000; i++) { - if(e.nextInt() < 100) { + if(e.nextValue() < 100) { j++; } } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/FileGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/FileGenerator.java index e39ffedc..ca10a1cb 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/FileGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/FileGenerator.java @@ -15,57 +15,48 @@ package com.yahoo.ycsb.generator; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; +import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; +import java.io.Reader; /** * A generator, whose sequence is the lines of a file. */ -public class FileGenerator extends Generator +public class FileGenerator extends Generator<String> { - String filename; - String current; - BufferedReader reader; + private final String filename; + private String current; + private BufferedReader reader; /** * Create a FileGenerator with the given file. * @param _filename The file to read lines from. */ - public FileGenerator(String _filename) + public FileGenerator(String _filename) { - try { - filename = _filename; - File file = new File(filename); - FileInputStream in = new FileInputStream(file); - reader = new BufferedReader(new InputStreamReader(in)); - } catch(IOException e) { - System.err.println("Exception: " + e); - } + filename = _filename; + reloadFile(); } /** * Return the next string of the sequence, ie the next line of the file. */ - public synchronized String nextString() + @Override + public synchronized String nextValue() { try { return current = reader.readLine(); - } catch(NullPointerException e) { - System.err.println("NullPointerException: " + filename + ':' + current); - throw e; } catch(IOException e) { - System.err.println("Exception: " + e); - return null; + throw new RuntimeException(e); } } /** * Return the previous read line. */ - public String lastString() + @Override + public String lastValue() { return current; } @@ -73,16 +64,12 @@ public class FileGenerator extends Generator /** * Reopen the file to reuse values. */ - public synchronized void reloadFile() - { - try { + public synchronized void reloadFile() { + try (Reader r = reader) { System.err.println("Reload " + filename); - reader.close(); - File file = new File(filename); - FileInputStream in = new FileInputStream(file); - reader = new BufferedReader(new InputStreamReader(in)); - } catch(IOException e) { - System.err.println("Exception: " + e); - } + reader = new BufferedReader(new FileReader(filename)); + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/Generator.java b/core/src/main/java/com/yahoo/ycsb/generator/Generator.java index a0d2f2e6..73e5ca1a 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/Generator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/Generator.java @@ -18,20 +18,30 @@ package com.yahoo.ycsb.generator; /** - * An expression that generates a sequence of string values, following some distribution (Uniform, Zipfian, Sequential, etc.) + * An expression that generates a sequence of values, following some distribution (Uniform, Zipfian, Sequential, etc.) */ -public abstract class Generator +public abstract class Generator<V> { /** - * Generate the next string in the distribution. + * Generate the next value in the distribution. */ - public abstract String nextString(); + public abstract V nextValue(); /** - * Return the previous string generated by the distribution; e.g., returned from the last nextString() call. - * Calling lastString() should not advance the distribution or have any side effects. If nextString() has not yet - * been called, lastString() should return something reasonable. + * Return the previous value generated by the distribution; e.g., returned from the last {@link Generator#nextValue()} call. + * Calling {@link #lastValue()} should not advance the distribution or have any side effects. If {@link #nextValue()} has not yet + * been called, {@link #lastValue()} should return something reasonable. */ - public abstract String lastString(); + public abstract V lastValue(); + + public final String nextString() { + V ret = nextValue(); + return ret == null ? null : ret.toString(); + } + + public final String lastString() { + V ret = lastValue(); + return ret == null ? null : ret.toString(); + } } 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 aba42c47..55a2e8d9 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/HistogramGenerator.java @@ -19,10 +19,8 @@ import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; -import java.util.Random; - import com.yahoo.ycsb.Utils; -import com.yahoo.ycsb.generator.IntegerGenerator; +import com.yahoo.ycsb.generator.NumberGenerator; /** * Generate integers according to a histogram distribution. The histogram @@ -38,44 +36,43 @@ import com.yahoo.ycsb.generator.IntegerGenerator; * @author snjones * */ -public class HistogramGenerator extends IntegerGenerator { +public class HistogramGenerator extends NumberGenerator { - long block_size; - long[] buckets; - long area; - long weighted_area = 0; - double mean_size = 0; + private final long block_size; + private final long[] buckets; + private long area; + private long weighted_area = 0; + private double mean_size = 0; public HistogramGenerator(String histogramfile) throws IOException { - BufferedReader in = new BufferedReader(new FileReader(histogramfile)); - String str; - String[] line; - - ArrayList<Integer> a = new ArrayList<Integer>(); - - str = in.readLine(); - if(str == null) { - throw new IOException("Empty input file!\n"); - } - line = str.split("\t"); - if(line[0].compareTo("BlockSize") != 0) { - throw new IOException("First line of histogram is not the BlockSize!\n"); - } - block_size = Integer.parseInt(line[1]); - - while((str = in.readLine()) != null){ - // [0] is the bucket, [1] is the value - line = str.split("\t"); - - a.add(Integer.parseInt(line[0]), Integer.parseInt(line[1])); - } - buckets = new long[a.size()]; - for(int i = 0; i < a.size(); i++) { - buckets[i] = a.get(i); - } - - in.close(); - init(); + try (BufferedReader in = new BufferedReader(new FileReader(histogramfile))) { + String str; + String[] line; + + ArrayList<Integer> a = new ArrayList<Integer>(); + + str = in.readLine(); + if(str == null) { + throw new IOException("Empty input file!\n"); + } + line = str.split("\t"); + if(line[0].compareTo("BlockSize") != 0) { + throw new IOException("First line of histogram is not the BlockSize!\n"); + } + block_size = Integer.parseInt(line[1]); + + while((str = in.readLine()) != null){ + // [0] is the bucket, [1] is the value + line = str.split("\t"); + + a.add(Integer.parseInt(line[0]), Integer.parseInt(line[1])); + } + buckets = new long[a.size()]; + for(int i = 0; i < a.size(); i++) { + buckets[i] = a.get(i); + } + } + init(); } public HistogramGenerator(long[] buckets, int block_size) { @@ -89,22 +86,22 @@ public class HistogramGenerator extends IntegerGenerator { weighted_area = i * buckets[i]; } // calculate average file size - mean_size = ((double)block_size) * ((double)weighted_area) / (double)(area); + mean_size = ((double)block_size) * ((double)weighted_area) / (area); } @Override - public int nextInt() { + public Long nextValue() { int number = Utils.random().nextInt((int)area); int i; for(i = 0; i < (buckets.length - 1); i++){ number -= buckets[i]; if(number <= 0){ - return (int)((i+1)*block_size); + return (i+1)*block_size; } } - return (int)(i * block_size); + return i * block_size; } @Override 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 969ae770..fafe8ff4 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/HotspotIntegerGenerator.java @@ -31,7 +31,7 @@ import com.yahoo.ycsb.Utils; * @author sudipto * */ -public class HotspotIntegerGenerator extends IntegerGenerator { +public class HotspotIntegerGenerator extends NumberGenerator { private final int lowerBound; private final int upperBound; @@ -75,7 +75,7 @@ public class HotspotIntegerGenerator extends IntegerGenerator { } @Override - public int nextInt() { + public Integer nextValue() { int value = 0; Random random = Utils.random(); if (random.nextDouble() < hotOpnFraction) { @@ -85,7 +85,7 @@ public class HotspotIntegerGenerator extends IntegerGenerator { // Choose a value from the cold set. value = lowerBound + hotInterval + random.nextInt(coldInterval); } - setLastInt(value); + setLastValue(value); return value; } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/IntegerGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/NumberGenerator.java similarity index 67% rename from core/src/main/java/com/yahoo/ycsb/generator/IntegerGenerator.java rename to core/src/main/java/com/yahoo/ycsb/generator/NumberGenerator.java index 16e99531..59d89341 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/IntegerGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/NumberGenerator.java @@ -18,55 +18,29 @@ package com.yahoo.ycsb.generator; /** - * A generator that is capable of generating ints as well as strings + * A generator that is capable of generating numeric values * * @author cooperb * */ -public abstract class IntegerGenerator extends Generator +public abstract class NumberGenerator extends Generator<Number> { - int lastint; + private Number lastVal; /** - * Set the last value generated. IntegerGenerator subclasses must use this call - * to properly set the last string value, or the lastString() and lastInt() calls won't work. + * Set the last value generated. NumberGenerator subclasses must use this call + * to properly set the last value, or the {@link #lastValue()} calls won't work. */ - protected void setLastInt(int last) + protected void setLastValue(Number last) { - lastint=last; + lastVal=last; } + - /** - * Return the next value as an int. When overriding this method, be sure to call setLastString() properly, or the lastString() call won't work. - */ - public abstract int nextInt(); - - /** - * Generate the next string in the distribution. - */ - public String nextString() - { - return String.valueOf(nextInt()); - } - - /** - * Return the previous string generated by the distribution; e.g., returned from the last nextString() call. - * Calling lastString() should not advance the distribution or have any side effects. If nextString() has not yet - * been called, lastString() should return something reasonable. - */ @Override - public String lastString() - { - return String.valueOf(lastInt()); - } - - /** - * Return the previous int generated by the distribution. This call is unique to IntegerGenerator subclasses, and assumes - * IntegerGenerator subclasses always return ints for nextInt() (e.g. not arbitrary strings). - */ - public int lastInt() + public Number lastValue() { - return lastint; + return lastVal; } /** * Return the expected value (mean) of the values this generator will return. diff --git a/core/src/main/java/com/yahoo/ycsb/generator/ScrambledZipfianGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/ScrambledZipfianGenerator.java index 4b851272..8918c371 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ScrambledZipfianGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ScrambledZipfianGenerator.java @@ -28,14 +28,14 @@ import com.yahoo.ycsb.Utils; * Unlike @ZipfianGenerator, this class scatters the "popular" items across the itemspace. Use this, instead of @ZipfianGenerator, if you * don't want the head of the distribution (the popular items) clustered together. */ -public class ScrambledZipfianGenerator extends IntegerGenerator +public class ScrambledZipfianGenerator extends NumberGenerator { public static final double ZETAN=26.46902820178302; public static final double USED_ZIPFIAN_CONSTANT=0.99; public static final long ITEM_COUNT=10000000000L; - ZipfianGenerator gen; - long _min,_max,_itemcount; + private ZipfianGenerator gen; + private final long _min,_max,_itemcount; /******************************* Constructors **************************************/ @@ -94,22 +94,15 @@ public class ScrambledZipfianGenerator extends IntegerGenerator /**************************************************************************************************/ - /** - * Return the next int in the sequence. - */ - @Override - public int nextInt() { - return (int)nextLong(); - } - /** * Return the next long in the sequence. */ - public long nextLong() + @Override + public Long nextValue() { - long ret=gen.nextLong(); + long ret=gen.nextValue(); ret=_min+Utils.FNVhash64(ret)%_itemcount; - setLastInt((int)ret); + setLastValue(ret); return ret; } @@ -123,7 +116,7 @@ public class ScrambledZipfianGenerator extends IntegerGenerator for (int i=0; i<1000000; i++) { - System.out.println(gen.nextInt()); + System.out.println(""+gen.nextValue()); } } @@ -132,6 +125,6 @@ public class ScrambledZipfianGenerator extends IntegerGenerator */ @Override public double mean() { - return ((double)(((long)_min) +(long)_max))/2.0; + return ((_min) +_max)/2.0; } } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/SkewedLatestGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/SkewedLatestGenerator.java index 376eb777..f52f3c44 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/SkewedLatestGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/SkewedLatestGenerator.java @@ -20,27 +20,28 @@ package com.yahoo.ycsb.generator; /** * Generate a popularity distribution of items, skewed to favor recent items significantly more than older items. */ -public class SkewedLatestGenerator extends IntegerGenerator +public class SkewedLatestGenerator extends NumberGenerator { - CounterGenerator _basis; - ZipfianGenerator _zipfian; + private CounterGenerator _basis; + private final ZipfianGenerator _zipfian; public SkewedLatestGenerator(CounterGenerator basis) { _basis=basis; - _zipfian=new ZipfianGenerator(_basis.lastInt()); - nextInt(); + _zipfian=new ZipfianGenerator(_basis.lastValue()); + nextValue(); } /** * Generate the next string in the distribution, skewed Zipfian favoring the items most recently returned by the basis generator. */ - public int nextInt() + @Override + public Long nextValue() { - int max=_basis.lastInt(); - int nextint=max-_zipfian.nextInt(max); - setLastInt(nextint); - return nextint; + long max=_basis.lastValue(); + long next=max-_zipfian.nextLong(max); + setLastValue(next); + return next; } public static void main(String[] args) diff --git a/core/src/main/java/com/yahoo/ycsb/generator/UniformGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/UniformGenerator.java index 43b9d390..5567225c 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/UniformGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/UniformGenerator.java @@ -17,26 +17,27 @@ package com.yahoo.ycsb.generator; -import java.util.Vector; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** - * An expression that generates a random integer in the specified range + * An expression that generates a random value in the specified range */ -public class UniformGenerator extends Generator +public class UniformGenerator extends Generator<String> { - Vector<String> _values; - String _laststring; - UniformIntegerGenerator _gen; + private final List<String> _values; + private String _laststring; + private final UniformIntegerGenerator _gen; /** * Creates a generator that will return strings from the specified set uniformly randomly */ - @SuppressWarnings( "unchecked" ) - public UniformGenerator(Vector<String> values) + public UniformGenerator(Collection<String> values) { - _values=(Vector<String>)values.clone(); + _values= new ArrayList<>(values); _laststring=null; _gen=new UniformIntegerGenerator(0,values.size()-1); } @@ -44,9 +45,10 @@ public class UniformGenerator extends Generator /** * Generate the next string in the distribution. */ - public String nextString() + @Override + public String nextValue() { - _laststring=_values.elementAt(_gen.nextInt()); + _laststring = _values.get(_gen.nextValue()); return _laststring; } @@ -55,11 +57,12 @@ public class UniformGenerator extends Generator * Calling lastString() should not advance the distribution or have any side effects. If nextString() has not yet * been called, lastString() should return something reasonable. */ - public String lastString() + @Override + public String lastValue() { if (_laststring==null) { - nextString(); + nextValue(); } return _laststring; } diff --git a/core/src/main/java/com/yahoo/ycsb/generator/UniformIntegerGenerator.java b/core/src/main/java/com/yahoo/ycsb/generator/UniformIntegerGenerator.java index fa6af131..3e2c99d9 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/UniformIntegerGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/UniformIntegerGenerator.java @@ -17,16 +17,14 @@ package com.yahoo.ycsb.generator; -import java.util.Random; - import com.yahoo.ycsb.Utils; /** * Generates integers randomly uniform from an interval. */ -public class UniformIntegerGenerator extends IntegerGenerator +public class UniformIntegerGenerator extends NumberGenerator { - int _lb,_ub,_interval; + private final int _lb,_ub,_interval; /** * Creates a generator that will return integers uniformly randomly from the interval [lb,ub] inclusive (that is, lb and ub are possible values) @@ -42,16 +40,16 @@ public class UniformIntegerGenerator extends IntegerGenerator } @Override - public int nextInt() + public Integer nextValue() { int ret=Utils.random().nextInt(_interval)+_lb; - setLastInt(ret); + setLastValue(ret); return ret; } @Override public double mean() { - return ((double)((long)(_lb + (long)_ub))) / 2.0; + return ((_lb + (long)_ub)) / 2.0; } } 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 017fa05e..3bd445f7 100644 --- a/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java +++ b/core/src/main/java/com/yahoo/ycsb/generator/ZipfianGenerator.java @@ -17,8 +17,6 @@ package com.yahoo.ycsb.generator; -import java.util.Random; - import com.yahoo.ycsb.Utils; /** @@ -39,34 +37,34 @@ import com.yahoo.ycsb.Utils; * * The algorithm used here is from "Quickly Generating Billion-Record Synthetic Databases", Jim Gray et al, SIGMOD 1994. */ -public class ZipfianGenerator extends IntegerGenerator +public class ZipfianGenerator extends NumberGenerator { public static final double ZIPFIAN_CONSTANT=0.99; /** * Number of items. */ - long items; + private final long items; /** * Min item to generate. */ - long base; + private final long base; /** * The zipfian constant to use. */ - double zipfianconstant; + private final double zipfianconstant; /** * Computed parameters for generating the distribution. */ - double alpha,zetan,eta,theta,zeta2theta; + private double alpha,zetan,eta,theta,zeta2theta; /** * The number of items used to compute zetan the last time. */ - long countforzeta; + private long countforzeta; /** * Flag to prevent problems. If you increase the number of items the zipfian generator is allowed to choose from, this code will incrementally compute a new zeta @@ -76,7 +74,7 @@ public class ZipfianGenerator extends IntegerGenerator * did the second thread think there were only 1000 items? maybe it read the item count before the first thread incremented it. So this flag allows you to say if you really do * want that recomputation. If true, then the code will recompute zeta if the itemcount goes down. If false, the code will assume itemcount only goes up, and never recompute. */ - boolean allowitemcountdecrease=false; + private boolean allowitemcountdecrease=false; /******************************* Constructors **************************************/ @@ -148,7 +146,7 @@ public class ZipfianGenerator extends IntegerGenerator eta=(1-Math.pow(2.0/items,1-theta))/(1-zeta2theta/zetan); //System.out.println("XXXX 3 XXXX"); - nextInt(); + nextValue(); //System.out.println("XXXX 4 XXXX"); } @@ -219,16 +217,6 @@ public class ZipfianGenerator extends IntegerGenerator /****************************************************************************************/ - /** - * Generate the next item. this distribution will be skewed toward lower integers; e.g. 0 will - * be the most popular, 1 the next most popular, etc. - * @param itemcount The number of items in the distribution. - * @return The next item in the sequence. - */ - public int nextInt(int itemcount) - { - return (int)nextLong(itemcount); - } /** * Generate the next item as a long. @@ -236,7 +224,7 @@ public class ZipfianGenerator extends IntegerGenerator * @param itemcount The number of items in the distribution. * @return The next item in the sequence. */ - public long nextLong(long itemcount) + long nextLong(long itemcount) { //from "Quickly Generating Billion-Record Synthetic Databases", Jim Gray et al, SIGMOD 1994 @@ -285,7 +273,7 @@ public class ZipfianGenerator extends IntegerGenerator } long ret=base+(long)((itemcount) * Math.pow(eta*u - eta + 1, alpha)); - setLastInt((int)ret); + setLastValue(ret); return ret; } @@ -295,17 +283,7 @@ public class ZipfianGenerator extends IntegerGenerator * popular items scattered throughout the item space, use ScrambledZipfianGenerator instead. */ @Override - public int nextInt() - { - return (int)nextLong(items); - } - - /** - * Return the next value, skewed by the Zipfian distribution. The 0th item will be the most popular, followed by the 1st, followed - * by the 2nd, etc. (Or, if min != 0, the min-th item is the most popular, the min+1th item the next most popular, etc.) If you want the - * popular items scattered throughout the item space, use ScrambledZipfianGenerator instead. - */ - public long nextLong() + public Long nextValue() { return nextLong(items); } diff --git a/core/src/main/java/com/yahoo/ycsb/workloads/ConstantOccupancyWorkload.java b/core/src/main/java/com/yahoo/ycsb/workloads/ConstantOccupancyWorkload.java index 39f24ade..3f367c7a 100644 --- a/core/src/main/java/com/yahoo/ycsb/workloads/ConstantOccupancyWorkload.java +++ b/core/src/main/java/com/yahoo/ycsb/workloads/ConstantOccupancyWorkload.java @@ -20,7 +20,7 @@ import java.util.Properties; import com.yahoo.ycsb.WorkloadException; import com.yahoo.ycsb.Client; -import com.yahoo.ycsb.generator.IntegerGenerator; +import com.yahoo.ycsb.generator.NumberGenerator; /** * A disk-fragmenting workload. @@ -45,12 +45,11 @@ import com.yahoo.ycsb.generator.IntegerGenerator; * */ public class ConstantOccupancyWorkload extends CoreWorkload { - long disksize; - long storageages; - IntegerGenerator objectsizes; + private long disksize; + private long storageages; double occupancy; - long object_count; + private long object_count; public static final String STORAGE_AGE_PROPERTY = "storageages"; public static final long STORAGE_AGE_PROPERTY_DEFAULT = 10; @@ -73,11 +72,11 @@ public class ConstantOccupancyWorkload extends CoreWorkload { p.getProperty(Client.OPERATION_COUNT_PROPERTY) != null) { System.err.println("Warning: record, insert or operation count was set prior to initting ConstantOccupancyWorkload. Overriding old values."); } - IntegerGenerator g = CoreWorkload.getFieldLengthGenerator(p); + NumberGenerator g = CoreWorkload.getFieldLengthGenerator(p); double fieldsize = g.mean(); int fieldcount = Integer.parseInt(p.getProperty(FIELD_COUNT_PROPERTY, FIELD_COUNT_PROPERTY_DEFAULT)); - object_count = (long)(occupancy * ((double)disksize / (fieldsize * (double)fieldcount))); + object_count = (long)(occupancy * (disksize / (fieldsize * fieldcount))); if(object_count == 0) { throw new IllegalStateException("Object count was zero. Perhaps disksize is too low?"); } diff --git a/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java b/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java index 52c0e50d..ad127d8b 100644 --- a/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java +++ b/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java @@ -24,11 +24,10 @@ import com.yahoo.ycsb.generator.AcknowledgedCounterGenerator; import com.yahoo.ycsb.generator.CounterGenerator; import com.yahoo.ycsb.generator.DiscreteGenerator; import com.yahoo.ycsb.generator.ExponentialGenerator; -import com.yahoo.ycsb.generator.Generator; import com.yahoo.ycsb.generator.ConstantIntegerGenerator; import com.yahoo.ycsb.generator.HotspotIntegerGenerator; import com.yahoo.ycsb.generator.HistogramGenerator; -import com.yahoo.ycsb.generator.IntegerGenerator; +import com.yahoo.ycsb.generator.NumberGenerator; import com.yahoo.ycsb.generator.ScrambledZipfianGenerator; import com.yahoo.ycsb.generator.SkewedLatestGenerator; import com.yahoo.ycsb.generator.UniformIntegerGenerator; @@ -138,7 +137,7 @@ public class CoreWorkload extends Workload { * Generator object that produces field lengths. The value of this depends on the properties that * start with "FIELD_LENGTH_". */ - IntegerGenerator fieldlengthgenerator; + NumberGenerator fieldlengthgenerator; /** * The name of the property for deciding whether to read one field (false) or all fields (true) of @@ -308,17 +307,17 @@ public class CoreWorkload extends Workload { public static final String INSERTION_RETRY_INTERVAL = "core_workload_insertion_retry_interval"; public static final String INSERTION_RETRY_INTERVAL_DEFAULT = "3"; - IntegerGenerator keysequence; + NumberGenerator keysequence; DiscreteGenerator operationchooser; - IntegerGenerator keychooser; + NumberGenerator keychooser; - Generator fieldchooser; + NumberGenerator fieldchooser; AcknowledgedCounterGenerator transactioninsertkeysequence; - IntegerGenerator scanlength; + NumberGenerator scanlength; boolean orderedinserts; @@ -329,8 +328,8 @@ public class CoreWorkload extends Workload { private Measurements _measurements = Measurements.getMeasurements(); - protected static IntegerGenerator getFieldLengthGenerator(Properties p) throws WorkloadException { - IntegerGenerator fieldlengthgenerator; + protected static NumberGenerator getFieldLengthGenerator(Properties p) throws WorkloadException { + NumberGenerator fieldlengthgenerator; String fieldlengthdistribution = p.getProperty( FIELD_LENGTH_DISTRIBUTION_PROPERTY, FIELD_LENGTH_DISTRIBUTION_PROPERTY_DEFAULT); int fieldlength = @@ -361,6 +360,7 @@ public class CoreWorkload extends Workload { * Initialize the scenario. * Called once, in the main client thread, before any operations are started. */ + @Override public void init(Properties p) throws WorkloadException { table = p.getProperty(TABLENAME_PROPERTY, TABLENAME_PROPERTY_DEFAULT); @@ -511,13 +511,13 @@ public class CoreWorkload extends Workload { private HashMap<String, ByteIterator> buildSingleValue(String key) { HashMap<String, ByteIterator> value = new HashMap<String, ByteIterator>(); - String fieldkey = fieldnames.get(Integer.parseInt(fieldchooser.nextString())); + String fieldkey = fieldnames.get(fieldchooser.nextValue().intValue()); ByteIterator data; if (dataintegrity) { data = new StringByteIterator(buildDeterministicValue(key, fieldkey)); } else { // fill with random data - data = new RandomByteIterator(fieldlengthgenerator.nextInt()); + data = new RandomByteIterator(fieldlengthgenerator.nextValue().longValue()); } value.put(fieldkey, data); @@ -536,7 +536,7 @@ public class CoreWorkload extends Workload { data = new StringByteIterator(buildDeterministicValue(key, fieldkey)); } else { // fill with random data - data = new RandomByteIterator(fieldlengthgenerator.nextInt()); + data = new RandomByteIterator(fieldlengthgenerator.nextValue().longValue()); } values.put(fieldkey, data); } @@ -547,7 +547,7 @@ public class CoreWorkload extends Workload { * Build a deterministic value given the key information. */ private String buildDeterministicValue(String key, String fieldkey) { - int size = fieldlengthgenerator.nextInt(); + int size = fieldlengthgenerator.nextValue().intValue(); StringBuilder sb = new StringBuilder(size); sb.append(key); sb.append(':'); @@ -567,8 +567,9 @@ public class CoreWorkload extends Workload { * for each other, and it will be difficult to reach the target throughput. Ideally, this function would * have no side effects other than DB operations. */ + @Override public boolean doInsert(DB db, Object threadstate) { - int keynum = keysequence.nextInt(); + int keynum = keysequence.nextValue().intValue(); String dbkey = buildKeyName(keynum); HashMap<String, ByteIterator> values = buildValues(dbkey); @@ -609,20 +610,25 @@ public class CoreWorkload extends Workload { * for each other, and it will be difficult to reach the target throughput. Ideally, this function would * have no side effects other than DB operations. */ + @Override public boolean doTransaction(DB db, Object threadstate) { - String op = operationchooser.nextString(); - - if (op.compareTo("READ") == 0) { - doTransactionRead(db); - } else if (op.compareTo("UPDATE") == 0) { - doTransactionUpdate(db); - } else if (op.compareTo("INSERT") == 0) { - doTransactionInsert(db); - } else if (op.compareTo("SCAN") == 0) { - doTransactionScan(db); - } else { - doTransactionReadModifyWrite(db); - } + switch (operationchooser.nextString()) { + + case "READ": + doTransactionRead(db); + break; + case "UPDATE": + doTransactionUpdate(db); + break; + case "INSERT": + doTransactionInsert(db); + break; + case "SCAN": + doTransactionScan(db); + break; + default: + doTransactionReadModifyWrite(db); + } return true; } @@ -657,12 +663,12 @@ public class CoreWorkload extends Workload { int keynum; if (keychooser instanceof ExponentialGenerator) { do { - keynum = transactioninsertkeysequence.lastInt() - keychooser.nextInt(); + keynum = transactioninsertkeysequence.lastValue() - keychooser.nextValue().intValue(); } while (keynum < 0); } else { do { - keynum = keychooser.nextInt(); - } while (keynum > transactioninsertkeysequence.lastInt()); + keynum = keychooser.nextValue().intValue(); + } while (keynum > transactioninsertkeysequence.lastValue()); } return keynum; } @@ -677,7 +683,7 @@ public class CoreWorkload extends Workload { if (!readallfields) { // read a random field - String fieldname = fieldnames.get(Integer.parseInt(fieldchooser.nextString())); + String fieldname = fieldnames.get(fieldchooser.nextValue().intValue()); fields = new HashSet<String>(); fields.add(fieldname); @@ -693,7 +699,7 @@ public class CoreWorkload extends Workload { verifyRow(keyname, cells); } } - + public void doTransactionReadModifyWrite(DB db) { // choose a random key int keynum = nextKeynum(); @@ -704,7 +710,7 @@ public class CoreWorkload extends Workload { if (!readallfields) { // read a random field - String fieldname = fieldnames.get(Integer.parseInt(fieldchooser.nextString())); + String fieldname = fieldnames.get(fieldchooser.nextValue().intValue()); fields = new HashSet<String>(); fields.add(fieldname); @@ -748,13 +754,13 @@ public class CoreWorkload extends Workload { String startkeyname = buildKeyName(keynum); // choose a random scan length - int len = scanlength.nextInt(); + int len = scanlength.nextValue().intValue(); HashSet<String> fields = null; if (!readallfields) { // read a random field - String fieldname = fieldnames.get(Integer.parseInt(fieldchooser.nextString())); + String fieldname = fieldnames.get(fieldchooser.nextValue().intValue()); fields = new HashSet<String>(); fields.add(fieldname); @@ -784,7 +790,7 @@ public class CoreWorkload extends Workload { public void doTransactionInsert(DB db) { // choose the next key - int keynum = transactioninsertkeysequence.nextInt(); + int keynum = transactioninsertkeysequence.nextValue(); try { String dbkey = buildKeyName(keynum); diff --git a/core/src/test/java/com/yahoo/ycsb/generator/AcknowledgedCounterGeneratorTest.java b/core/src/test/java/com/yahoo/ycsb/generator/AcknowledgedCounterGeneratorTest.java index 54e02322..f4aa88b4 100644 --- a/core/src/test/java/com/yahoo/ycsb/generator/AcknowledgedCounterGeneratorTest.java +++ b/core/src/test/java/com/yahoo/ycsb/generator/AcknowledgedCounterGeneratorTest.java @@ -40,7 +40,7 @@ public class AcknowledgedCounterGeneratorTest { Random rand = new Random(System.currentTimeMillis()); BlockingQueue<Integer> pending = new ArrayBlockingQueue<Integer>(1000); for (long i = 0; i < toTry; ++i) { - int value = generator.nextInt(); + int value = generator.nextValue(); while (!pending.offer(value)) { diff --git a/core/src/test/java/com/yahoo/ycsb/generator/TestZipfianGenerator.java b/core/src/test/java/com/yahoo/ycsb/generator/TestZipfianGenerator.java index 4b7cc2a4..77a77586 100644 --- a/core/src/test/java/com/yahoo/ycsb/generator/TestZipfianGenerator.java +++ b/core/src/test/java/com/yahoo/ycsb/generator/TestZipfianGenerator.java @@ -30,7 +30,7 @@ public class TestZipfianGenerator { ZipfianGenerator zipfian = new ZipfianGenerator(min, max); for (int i = 0; i < 10000; i++) { - long rnd = zipfian.nextLong(); + long rnd = zipfian.nextValue(); assertFalse(rnd < min); assertFalse(rnd > max); } diff --git a/core/src/test/java/com/yahoo/ycsb/measurements/exporter/TestMeasurementsExporter.java b/core/src/test/java/com/yahoo/ycsb/measurements/exporter/TestMeasurementsExporter.java index 1d24f9ae..4aff0941 100644 --- a/core/src/test/java/com/yahoo/ycsb/measurements/exporter/TestMeasurementsExporter.java +++ b/core/src/test/java/com/yahoo/ycsb/measurements/exporter/TestMeasurementsExporter.java @@ -42,7 +42,7 @@ public class TestMeasurementsExporter { long max = 100000; ZipfianGenerator zipfian = new ZipfianGenerator(min, max); for (int i = 0; i < 1000; i++) { - int rnd = zipfian.nextInt(); + int rnd = zipfian.nextValue().intValue(); mm.measure("UPDATE", rnd); } mm.exportMeasurements(export); -- GitLab