/* * Copyright 2011 Google 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. */ package com.googlecode.concurrentlinkedhashmap.benchmark; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayListWithCapacity; import com.googlecode.concurrentlinkedhashmap.generator.Generator; import com.googlecode.concurrentlinkedhashmap.generator.IntegerGenerator; import java.text.NumberFormat; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; /** * A set of utilities for writing benchmarks. * * @author ben.manes@gmail.com (Ben Manes) */ public final class Benchmarks { private Benchmarks() {} /** * Creates a random working set based on the distribution. * * @param generator the distribution generator * @param size the size of the working set * @return a random working set */ public static List<String> createWorkingSet(Generator generator, int size) { List<String> workingSet = newArrayListWithCapacity(size); for (int i = 0; i < size; i++) { workingSet.add(generator.nextString()); } return workingSet; } /** * Creates a random working set based on the distribution. * * @param generator the distribution generator * @param size the size of the working set * @return a random working set */ public static List<Integer> createWorkingSet(IntegerGenerator generator, int size) { Integer[] ints = new Integer[size]; for (int i = 0; i < ints.length; i++) { ints[i] = generator.nextInt(); } return Arrays.asList(ints); } /** * Based on the passed in working set, creates N shuffled variants. * * @param samples the number of variants to create * @param workingSet the base working set to build from */ public static <T> List<List<T>> shuffle(int samples, Collection<T> workingSet) { List<List<T>> sets = newArrayListWithCapacity(samples); for (int i = 0; i < samples; i++) { List<T> set = newArrayList(workingSet); Collections.shuffle(set); sets.add(set); } return sets; } /** * Determines the hit/miss rate of a cache. * * @param cache the self-evicting map * @param workingSet the request working set * @return the efficiency of the execution run */ public static <T> EfficiencyRun determineEfficiency(Map<T, T> cache, List<T> workingSet) { int hits = 0; for (T key : workingSet) { if (cache.get(key) == null) { cache.put(key, key); } else { hits++; } } return EfficiencyRun.of(hits, workingSet.size()); } public static final class EfficiencyRun { public final int hitCount; public final int missCount; public final double hitRate; public final double missRate; public final int workingSetSize; private EfficiencyRun(int hitCount, int workingSetSize) { this.workingSetSize = workingSetSize; this.hitCount = hitCount; this.missCount = workingSetSize - hitCount; this.hitRate = ((double) hitCount) / workingSetSize; this.missRate = ((double) missCount) / workingSetSize; } public static EfficiencyRun of(int hitCount, int workingSetSize) { return new EfficiencyRun(hitCount, workingSetSize); } @Override public String toString() { return String.format("hits=%s (%s percent), misses=%s (%s percent)", NumberFormat.getInstance().format(hitCount), NumberFormat.getPercentInstance().format(hitRate), NumberFormat.getInstance().format(missCount), NumberFormat.getPercentInstance().format(missRate)); } } }