package org.cache2k.benchmark.util; /* * #%L * Benchmarks: utilities * %% * Copyright (C) 2013 - 2017 headissue GmbH, Munich * %% * 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. * #L% */ /** * This code is adopted from the YCSB benchmark, * * original source: * https://github.com/brianfrankcooper/YCSB/blob/master/core/src/main/java/com/yahoo/ycsb/generator/ScrambledZipfianGenerator.java * * original license: * * 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 @ZipfianPattern, this class scatters the "popular" items across the itemspace. Use this, instead of @ZipfianPattern, if you * don't want the head of the distribution (the popular items) clustered together. */ public class ScrambledZipfianPattern extends AbstractEternalAccessPattern { ZipfianPattern 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 ScrambledZipfianPattern(long _randomSeed, long _items) { this(_randomSeed, 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 ScrambledZipfianPattern(long _randomSeed, long min, long max) { this(_randomSeed, min, max, ZipfianPattern.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. */ /* public ScrambledZipfianPattern(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 ScrambledZipfianPattern(long _randomSeed, long min, long max, double _zipfianconstant) { this.min = min; this.max = max; itemcount = this.max - this.min +1; if (_zipfianconstant == USED_ZIPFIAN_CONSTANT) { gen = new ZipfianPattern(_randomSeed, 0, ITEM_COUNT,_zipfianconstant,ZETAN); } else { gen = new ZipfianPattern(_randomSeed, 0, ITEM_COUNT,_zipfianconstant); } } /** * Return the next int in the sequence. */ int nextInt() { return (int)nextLong(); } /** * Return the next long in the sequence. */ long nextLong() { long ret = gen.nextLong(); ret = min + fNVhash64(ret) % itemcount; return ret; } @Override public int next() throws Exception { return nextInt(); } public static final double ZETAN = 26.46902820178302; public static final double USED_ZIPFIAN_CONSTANT=0.99; public static final long ITEM_COUNT=10000000000L; public static final long FNV_offset_basis_64 = 0xCBF29CE484222325L; public static final long FNV_prime_64 = 1099511628211L; /** * 64 bit FNV hash. Produces more "random" hashes than (say) String.hashCode(). * * @param val The value to hash. * @return The hash value */ public static long fNVhash64(long val) { long hashval = FNV_offset_basis_64; for (int i=0; i<8; i++) { long octet=val&0x00ff; val=val>>8; hashval = hashval ^ octet; hashval = hashval * FNV_prime_64; } return Math.abs(hashval); } }