package edu.brown.benchmark.ycsb.distributions; /** * Copyright (c) 2010 Yahoo! Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. See accompanying * LICENSE file. */ /** * A generator of a zipfian distribution. It produces a sequence of items, such that some items are more popular than others, according * to a zipfian distribution. When you construct an instance of this class, you specify the number of items in the set to draw from, either * by specifying an itemcount (so that the sequence is of items from 0 to itemcount-1) or by specifying a min and a max (so that the sequence is of * items from min to max inclusive). After you construct the instance, you can change the number of items by calling nextInt(itemcount) or nextLong(itemcount). * * 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 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; /******************************* Constructors **************************************/ /** * Create a zipfian generator for the specified number of items. * @param _items The number of items in the distribution. */ public ScrambledZipfianGenerator(long _items) { this(0,_items-1); } /** * Create a zipfian generator for items between min and max. * @param _min The smallest integer to generate in the sequence. * @param _max The largest integer to generate in the sequence. */ public ScrambledZipfianGenerator(long _min, long _max) { this(_min,_max,ZipfianGenerator.ZIPFIAN_CONSTANT); } /** * Create a zipfian generator for the specified number of items using the specified zipfian constant. * * @param _items The number of items in the distribution. * @param _zipfianconstant The zipfian constant to use. */ /* // not supported, as the value of zeta depends on the zipfian constant, and we have only precomputed zeta for one zipfian constant public ScrambledZipfianGenerator(long _items, double _zipfianconstant) { this(0,_items-1,_zipfianconstant); } */ /** * Create a zipfian generator for items between min and max (inclusive) for the specified zipfian constant. If you * use a zipfian constant other than 0.99, this will take a long time to complete because we need to recompute zeta. * @param min The smallest integer to generate in the sequence. * @param max The largest integer to generate in the sequence. * @param _zipfianconstant The zipfian constant to use. */ public ScrambledZipfianGenerator(long min, long max, double _zipfianconstant) { _min=min; _max=max; _itemcount=_max-_min+1; if (_zipfianconstant == USED_ZIPFIAN_CONSTANT) { gen=new ZipfianGenerator(0,ITEM_COUNT,_zipfianconstant,ZETAN); } else { gen=new ZipfianGenerator(0,ITEM_COUNT,_zipfianconstant); } } /**************************************************************************************************/ /** * Return the next int in the sequence. */ @Override public int nextInt() { return (int)nextLong(); } /** * Return the next long in the sequence. */ public long nextLong() { long ret=gen.nextLong(); ret=_min+Utils.FNVhash64(ret)%_itemcount; setLastInt((int)ret); return ret; } public static void main(String[] args) { double newzetan = ZipfianGenerator.zetastatic(ITEM_COUNT,ZipfianGenerator.ZIPFIAN_CONSTANT); System.out.println("zetan: "+newzetan); System.exit(0); ScrambledZipfianGenerator gen=new ScrambledZipfianGenerator(10000); for (int i=0; i<1000000; i++) { System.out.println(""+gen.nextInt()); } } /** * since the values are scrambled (hopefully uniformly), the mean is simply the middle of the range. */ @Override public double mean() { return ((double)(((long)_min) +(long)_max))/2.0; } }