org.caffinitas.ohc.OHCacheBuilder Maven / Gradle / Ivy
/*
* 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;
import java.util.concurrent.ScheduledExecutorService;
import org.caffinitas.ohc.chunked.OHCacheChunkedImpl;
import org.caffinitas.ohc.linked.OHCacheLinkedImpl;
/**
* Configures and builds OHC instance.
*
*
* Field
* Meaning
* Default
*
*
* {@code keySerializer}
* Serializer implementation used for keys
* Must be configured
*
*
* {@code valueSerializer}
* Serializer implementation used for values
* Must be configured
*
*
* {@code executorService}
* Executor service required for get operations using a cache loader. E.g. {@link org.caffinitas.ohc.OHCache#getWithLoaderAsync(Object, CacheLoader)}
* (Not configured by default meaning get operations with cache loader not supported by default)
*
*
* {@code segmentCount}
* Number of segments
* 2 * number of CPUs ({@code java.lang.Runtime.availableProcessors()})
*
*
* {@code hashTableSize}
* Initial size of each segment's hash table
* {@code 8192}
*
*
* {@code loadFactor}
* Hash table load factor. I.e. determines when rehashing occurs.
* {@code .75f}
*
*
* {@code capacity}
* Capacity of the cache in bytes
* 16 MB * number of CPUs ({@code java.lang.Runtime.availableProcessors()}), minimum 64 MB
*
*
* {@code chunkSize}
* If set and positive, the chunked implementation will be used and each segment
* will be divided into this amount of chunks.
* {@code 0} - i.e. linked implementation will be used
*
*
* {@code fixedEntrySize}
* If set and positive, the chunked implementation with fixed sized entries
* will be used. The parameter {@code chunkSize} must be set for fixed-sized entries.
* {@code 0} - i.e. linked implementation will be used,
* if {@code chunkSize} is also {@code 0}
*
*
* {@code maxEntrySize}
* Maximum size of a hash entry (including header, serialized key + serialized value)
* (not set, defaults to capacity divided by number of segments)
*
*
* {@code throwOOME}
* Throw {@code OutOfMemoryError} if off-heap allocation fails
* {@code false}
*
*
* {@code hashAlgorighm}
* Hash algorithm to use internally. Valid options are: {@code XX} for xx-hash, {@code MURMUR3} or {@code CRC32}
* Note: this setting does may only help to improve throughput in rare situations - i.e. if the key is
* very long and you've proven that it really improves performace
* {@code MURMUR3}
*
*
* {@code unlocked}
* If set to {@code true}, implementations will not perform any locking. The calling code has to take
* care of synchronized access. In order to create an instance for a thread-per-core implementation,
* set {@code segmentCount=1}, too.
* {@code false}
*
*
* {@code defaultTTLmillis}
* If set to a value {@code > 0}, implementations supporting TTLs will tag all entries with
* the given TTL in milliseconds.
* {@code 0}
*
*
* {@code timeoutsSlots}
* The number of timeouts slots for each segment - compare with hashed wheel timer.
* {@code 64}
*
*
* {@code timeoutsPrecision}
* The amount of time in milliseconds for each timeouts-slot.
* {@code 128}
*
*
*
* You may also use system properties prefixed with {@code org.caffinitas.org.} to other defaults.
* E.g. the system property {@code org.caffinitas.org.segmentCount} configures the default of the number of segments.
*
*
* @param cache key type
* @param cache value type
*/
public class OHCacheBuilder
{
private int segmentCount;
private int hashTableSize = 8192;
private long capacity;
private int chunkSize;
private CacheSerializer keySerializer;
private CacheSerializer valueSerializer;
private float loadFactor = .75f;
private int fixedKeySize;
private int fixedValueSize;
private long maxEntrySize;
private ScheduledExecutorService executorService;
private boolean throwOOME;
private HashAlgorithm hashAlgorighm = HashAlgorithm.MURMUR3;
private boolean unlocked;
private long defaultTTLmillis;
private int timeoutsSlots;
private int timeoutsPrecision;
private OHCacheBuilder()
{
int cpus = Runtime.getRuntime().availableProcessors();
segmentCount = roundUpToPowerOf2(cpus * 2, 1 << 30);
capacity = Math.min(cpus * 16, 64) * 1024 * 1024;
segmentCount = fromSystemProperties("segmentCount", segmentCount);
hashTableSize = fromSystemProperties("hashTableSize", hashTableSize);
capacity = fromSystemProperties("capacity", capacity);
chunkSize = fromSystemProperties("chunkSize", chunkSize);
loadFactor = fromSystemProperties("loadFactor", loadFactor);
maxEntrySize = fromSystemProperties("maxEntrySize", maxEntrySize);
throwOOME = fromSystemProperties("throwOOME", throwOOME);
hashAlgorighm = HashAlgorithm.valueOf(fromSystemProperties("hashAlgorighm", hashAlgorighm.name()));
unlocked = fromSystemProperties("unlocked", unlocked);
defaultTTLmillis = fromSystemProperties("defaultTTLmillis", defaultTTLmillis);
timeoutsSlots = fromSystemProperties("timeoutsSlots", timeoutsSlots);
timeoutsPrecision = fromSystemProperties("timeoutsPrecision", timeoutsPrecision);
}
public static final String SYSTEM_PROPERTY_PREFIX = "org.caffinitas.ohc.";
private static float fromSystemProperties(String name, float defaultValue)
{
try
{
return Float.parseFloat(System.getProperty(SYSTEM_PROPERTY_PREFIX + name, Float.toString(defaultValue)));
}
catch (Exception e)
{
throw new RuntimeException("Failed to parse system property " + SYSTEM_PROPERTY_PREFIX + name, e);
}
}
private static long fromSystemProperties(String name, long defaultValue)
{
try
{
return Long.parseLong(System.getProperty(SYSTEM_PROPERTY_PREFIX + name, Long.toString(defaultValue)));
}
catch (Exception e)
{
throw new RuntimeException("Failed to parse system property " + SYSTEM_PROPERTY_PREFIX + name, e);
}
}
private static int fromSystemProperties(String name, int defaultValue)
{
try
{
return Integer.parseInt(System.getProperty(SYSTEM_PROPERTY_PREFIX + name, Integer.toString(defaultValue)));
}
catch (Exception e)
{
throw new RuntimeException("Failed to parse system property " + SYSTEM_PROPERTY_PREFIX + name, e);
}
}
private static boolean fromSystemProperties(String name, boolean defaultValue)
{
try
{
return Boolean.parseBoolean(System.getProperty(SYSTEM_PROPERTY_PREFIX + name, Boolean.toString(defaultValue)));
}
catch (Exception e)
{
throw new RuntimeException("Failed to parse system property " + SYSTEM_PROPERTY_PREFIX + name, e);
}
}
private static String fromSystemProperties(String name, String defaultValue)
{
return System.getProperty(SYSTEM_PROPERTY_PREFIX + name, defaultValue);
}
static int roundUpToPowerOf2(int number, int max)
{
return number >= max
? max
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}
public static OHCacheBuilder newBuilder()
{
return new OHCacheBuilder<>();
}
public OHCache build()
{
if (fixedKeySize > 0 || fixedValueSize > 0|| chunkSize > 0)
return new OHCacheChunkedImpl<>(this);
return new OHCacheLinkedImpl<>(this);
}
public int getHashTableSize()
{
return hashTableSize;
}
public OHCacheBuilder hashTableSize(int hashTableSize)
{
if (hashTableSize < -1)
throw new IllegalArgumentException("hashTableSize:" + hashTableSize);
this.hashTableSize = hashTableSize;
return this;
}
public int getChunkSize()
{
return chunkSize;
}
public OHCacheBuilder chunkSize(int chunkSize)
{
if (chunkSize < -1)
throw new IllegalArgumentException("chunkSize:" + chunkSize);
this.chunkSize = chunkSize;
return this;
}
public long getCapacity()
{
return capacity;
}
public OHCacheBuilder capacity(long capacity)
{
if (capacity <= 0)
throw new IllegalArgumentException("capacity:" + capacity);
this.capacity = capacity;
return this;
}
public CacheSerializer getKeySerializer()
{
return keySerializer;
}
public OHCacheBuilder keySerializer(CacheSerializer keySerializer)
{
this.keySerializer = keySerializer;
return this;
}
public CacheSerializer getValueSerializer()
{
return valueSerializer;
}
public OHCacheBuilder valueSerializer(CacheSerializer valueSerializer)
{
this.valueSerializer = valueSerializer;
return this;
}
public int getSegmentCount()
{
return segmentCount;
}
public OHCacheBuilder segmentCount(int segmentCount)
{
if (segmentCount < -1)
throw new IllegalArgumentException("segmentCount:" + segmentCount);
this.segmentCount = segmentCount;
return this;
}
public float getLoadFactor()
{
return loadFactor;
}
public OHCacheBuilder loadFactor(float loadFactor)
{
if (loadFactor <= 0f)
throw new IllegalArgumentException("loadFactor:" + loadFactor);
this.loadFactor = loadFactor;
return this;
}
public long getMaxEntrySize()
{
return maxEntrySize;
}
public OHCacheBuilder maxEntrySize(long maxEntrySize)
{
if (maxEntrySize < 0)
throw new IllegalArgumentException("maxEntrySize:" + maxEntrySize);
this.maxEntrySize = maxEntrySize;
return this;
}
public int getFixedKeySize()
{
return fixedKeySize;
}
public int getFixedValueSize()
{
return fixedValueSize;
}
public OHCacheBuilder fixedEntrySize(int fixedKeySize, int fixedValueSize)
{
if ((fixedKeySize > 0 || fixedValueSize > 0) &&
(fixedKeySize <= 0 || fixedValueSize <= 0))
throw new IllegalArgumentException("fixedKeySize:" + fixedKeySize+",fixedValueSize:" + fixedValueSize);
this.fixedKeySize = fixedKeySize;
this.fixedValueSize = fixedValueSize;
return this;
}
public ScheduledExecutorService getExecutorService()
{
return executorService;
}
public OHCacheBuilder executorService(ScheduledExecutorService executorService)
{
this.executorService = executorService;
return this;
}
public HashAlgorithm getHashAlgorighm()
{
return hashAlgorighm;
}
public OHCacheBuilder hashMode(HashAlgorithm hashMode)
{
if (hashMode == null)
throw new NullPointerException("hashMode");
this.hashAlgorighm = hashMode;
return this;
}
public boolean isThrowOOME()
{
return throwOOME;
}
public OHCacheBuilder throwOOME(boolean throwOOME)
{
this.throwOOME = throwOOME;
return this;
}
public boolean isUnlocked()
{
return unlocked;
}
public OHCacheBuilder unlocked(boolean unlocked)
{
this.unlocked = unlocked;
return this;
}
public long getDefaultTTLmillis()
{
return defaultTTLmillis;
}
public OHCacheBuilder defaultTTLmillis(long defaultTTLmillis)
{
this.defaultTTLmillis = defaultTTLmillis;
return this;
}
public int getTimeoutsSlots()
{
return timeoutsSlots;
}
public OHCacheBuilder timeoutsSlots(int timeoutsSlots)
{
this.timeoutsSlots = timeoutsSlots;
return this;
}
public int getTimeoutsPrecision()
{
return timeoutsPrecision;
}
public OHCacheBuilder timeoutsPrecision(int timeoutsPrecision)
{
this.timeoutsPrecision = timeoutsPrecision;
return this;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy