/*
* Copyright (C) 2014 Robert Stupp, Koeln, Germany, robert-stupp.de
*
* 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 org.caffinitas.ohc.jmh;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import org.caffinitas.ohc.Eviction;
import org.caffinitas.ohc.HashAlgorithm;
import org.caffinitas.ohc.OHCache;
import org.caffinitas.ohc.OHCacheBuilder;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
@BenchmarkMode({ /*Mode.AverageTime, */Mode.Throughput })
@State(Scope.Benchmark)
@Warmup(iterations = 2)
@Measurement(iterations = 3, time = 5)
@Threads(4)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Fork(value = 1, jvmArgsAppend = "-Xmx512M")
public class OHCBenchmark
{
private OHCache<Integer, byte[]> cache;
@Param({ "256"/*, "2048", "65536"*/ })
private int valueSz = 256;
@Param("1073741824")
private long capacity = 1024 * 1024 * 1024;
@Param("-1")
private int segCnt = -1;
@Param("-1")
private int hashTableSz = -1;
@Param("10000000")
private int keys = 10_000_000;
@Param({ "MURMUR3", "CRC32", "XX" })
private HashAlgorithm hashAlg = HashAlgorithm.MURMUR3;
@Param({ "-1", "65536"/*, "131072"*/ })
private int chunkSz = -1;
@Param("-1")
private int fixedKeyLen = -1;
@Param("-1")
private int fixedValLen = -1;
@Param({"LRU", "W_TINY_LFU"})
private Eviction eviction = Eviction.LRU;
private byte[] value;
@State(Scope.Thread)
public static class PutState
{
public int key = ThreadLocalRandom.current().nextInt(1000);
}
@State(Scope.Thread)
public static class GetState
{
public int key = ThreadLocalRandom.current().nextInt(1000);
public int run;
}
@Setup
public void setup() throws ClassNotFoundException
{
cache = OHCacheBuilder.<Integer, byte[]>newBuilder()
.capacity(capacity)
.segmentCount(segCnt)
.hashTableSize(hashTableSz)
.keySerializer(Utils.intSerializer)
.valueSerializer(Utils.byteArraySerializer)
.chunkSize(chunkSz)
.fixedEntrySize(fixedKeyLen, fixedValLen)
.hashMode(hashAlg)
.eviction(eviction)
.build();
value = new byte[valueSz];
for (int i = 0; i < keys; i++)
cache.put(i, value);
}
@TearDown
public void tearDown() throws IOException
{
cache.close();
}
@Benchmark
@Threads(value = 4)
public void getNonExisting()
{
cache.get(0);
}
@Benchmark
@Threads(value = 4)
public void containsNonExisting()
{
cache.containsKey(0);
}
@Benchmark
@Threads(value = 1)
public void putSingleThreaded(PutState state)
{
cache.put(state.key++, value);
if (state.key > keys)
state.key = 1;
}
@Benchmark
@Threads(value = 4)
public void putMultiThreaded(PutState state)
{
cache.put(state.key++, value);
if (state.key > keys)
state.key = 1;
}
@Benchmark
@Threads(value = 1)
public void getSingleThreaded(GetState state)
{
cache.get(state.key++);
if (state.key > keys)
state.key = 1;
}
@Benchmark
@Threads(value = 4)
public void getMultiThreaded(GetState state)
{
cache.get(state.key++);
state.run ++;
if (state.run < 4)
{
if (state.key > keys / 5)
state.key = 1;
}
state.run = 0;
if (state.key > keys)
state.key = 1;
}
}