Skip to content

Commit

Permalink
Add Collision cache to simulator and benchmarks (closes #126)
Browse files Browse the repository at this point in the history
Due to requiring JDK9 this cannot be enabled by default. An easy way to
run when enabled is using,
  $ jenv shell 9-ea
  $ gradle status --stop
  $ gradle simulator:run --no-daemon

For details on this implementation see
https://github.com/jamespedwards42/collision
  • Loading branch information
jpe42 authored and ben-manes committed Oct 13, 2016
1 parent 45deefd commit 260ec05
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ bin
build
test-output
jitwatch.out
.java-version
.DS_Store
.classpath
.settings
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ subprojects {
if (JavaVersion.current().isJava9Compatible()) {
tasks.uploadArchives.enabled = false
} else {
apply plugin: 'net.ltgt.errorprone'
apply plugin: 'net.ltgt.errorprone'
}

sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
1 change: 1 addition & 0 deletions caffeine/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dependencies {
jmh benchmark_libraries.ehcache3
jmh benchmark_libraries.koloboke
jmh benchmark_libraries.slf4j_nop
jmh benchmark_libraries.collision
jmh benchmark_libraries.infinispan
jmh benchmark_libraries.jackrabbit
jmh benchmark_libraries.elastic_search
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import com.github.benmanes.caffeine.cache.impl.Cache2k;
import com.github.benmanes.caffeine.cache.impl.CaffeineCache;
import com.github.benmanes.caffeine.cache.impl.Collision;
import com.github.benmanes.caffeine.cache.impl.ConcurrentHashMapV7;
import com.github.benmanes.caffeine.cache.impl.ConcurrentMapCache;
import com.github.benmanes.caffeine.cache.impl.Ehcache2;
Expand Down Expand Up @@ -79,6 +80,11 @@ public enum CacheType {
return new CaffeineCache<>(maximumSize);
}
},
Collision {
@Override public <K, V> BasicCache<K, V> create(int maximumSize) {
return new Collision<>(maximumSize);
}
},
ConcurrentLinkedHashMap {
@Override public <K, V> BasicCache<K, V> create(int maximumSize) {
return new ConcurrentMapCache<>(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2015 Ben Manes. 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.github.benmanes.caffeine.cache.impl;

import com.fabahaba.collision.cache.CollisionCache;
import com.github.benmanes.caffeine.cache.BasicCache;

/**
* Requires JDK9.
*
* @author [email protected] (Ben Manes)
*/
public final class Collision<K, V> implements BasicCache<K, V> {
private final CollisionCache<K, V> cache;

public Collision(int maximumSize) {
cache = CollisionCache.<V>withCapacity(maximumSize)
.setStrictCapacity(true)
.buildSparse();
}

@Override
public V get(K key) {
return cache.getIfPresent(key);
}

@Override
public void put(K key, V value) {
cache.putReplace(key, value);
}

@Override
public void clear() {
cache.clear();
}
}
1 change: 1 addition & 0 deletions config/pmd/rulesSets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<exclude name="AvoidReassigningParameters"/>
<exclude name="UncommentedEmptyConstructor"/>
<exclude name="UnnecessaryLocalBeforeReturn"/>
<exclude name="UseLocaleWithCaseConversions"/>
<exclude name="AvoidSynchronizedAtMethodLevel"/>
<exclude name="ConstructorCallsOverridableMethod"/>
<exclude name="PositionLiteralsFirstInComparisons"/>
Expand Down
4 changes: 3 additions & 1 deletion gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,14 @@ ext {
jcache_tck: '1.0.1',
jctools: '1.2.1',
junit: '4.12',
mockito: '2.2.0',
mockito: '2.2.1',
pax_exam: '4.9.1',
testng: '6.9.12',
truth: '0.24',
]
benchmark_versions = [
cache2k: '0.28-BETA',
collision: '0.2.4',
concurrentlinkedhashmap: '1.4.2',
ehcache2: '2.10.2.2.21',
ehcache3: '3.1.3',
Expand Down Expand Up @@ -136,6 +137,7 @@ ext {
]
benchmark_libraries = [
cache2k: "org.cache2k:cache2k-core:${benchmark_versions.cache2k}",
collision: "com.fabahaba:collision:${benchmark_versions.collision}",
concurrentlinkedhashmap: "com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:${benchmark_versions.concurrentlinkedhashmap}",
ehcache2: "net.sf.ehcache:ehcache:${benchmark_versions.ehcache2}",
ehcache3: "org.ehcache:ehcache:${benchmark_versions.ehcache3}",
Expand Down
1 change: 1 addition & 0 deletions simulator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ dependencies {
compile benchmark_libraries.cache2k
compile benchmark_libraries.ehcache2
compile benchmark_libraries.ehcache3
compile benchmark_libraries.collision
compile benchmark_libraries.slf4j_nop
compile benchmark_libraries.infinispan
compile benchmark_libraries.elastic_search
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.github.benmanes.caffeine.cache.simulator.policy.opt.UnboundedPolicy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.Cache2kPolicy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.CaffeinePolicy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.CollisionPolicy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.Ehcache2Policy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.Ehcache3Policy;
import com.github.benmanes.caffeine.cache.simulator.policy.product.ElasticSearchPolicy;
Expand Down Expand Up @@ -155,6 +156,7 @@ private static void registerProduct(Map<String, Function<Config, Set<Policy>>> f
factories.put("product.ehcache2", Ehcache2Policy::policies);
factories.put("product.ehcache3", Ehcache3Policy::policies);
factories.put("product.caffeine", CaffeinePolicy::policies);
factories.put("product.collision", CollisionPolicy::policies);
factories.put("product.infinispan", InfinispanPolicy::policies);
factories.put("product.elasticsearch", ElasticSearchPolicy::policies);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright 2016 Ben Manes. 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.github.benmanes.caffeine.cache.simulator.policy.product;

import static java.util.stream.Collectors.toSet;

import java.util.Set;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;

import com.fabahaba.collision.cache.CollisionBuilder;
import com.fabahaba.collision.cache.CollisionCache;
import com.github.benmanes.caffeine.cache.simulator.BasicSettings;
import com.github.benmanes.caffeine.cache.simulator.policy.Policy;
import com.github.benmanes.caffeine.cache.simulator.policy.PolicyStats;
import com.typesafe.config.Config;

/**
* Collision cache implementation.
*
* @author [email protected] (Ben Manes)
*/
public final class CollisionPolicy implements Policy {
private final CollisionCache<Object, Object> cache;
private final PolicyStats policyStats;
private final int maximumSize;

private int trackedSize;

public CollisionPolicy(CollisionSettings settings, Density density) {
policyStats = new PolicyStats(String.format("product.Collision (%s)",
StringUtils.capitalize(density.name().toLowerCase())));
maximumSize = settings.maximumSize();

CollisionBuilder<Object> builder = CollisionCache
.withCapacity(maximumSize)
.setInitCount(settings.initCount())
.setBucketSize(settings.bucketSize())
.setStrictCapacity(settings.strictCapacity());

if (density == Density.SPARSE) {
cache = builder.buildSparse(settings.sparseFactor());
} else if (density == Density.PACKED) {
cache = builder.buildPacked();
} else {
throw new IllegalArgumentException();
}
}

/** Returns all variations of this policy based on the configuration parameters. */
public static Set<Policy> policies(Config config) {
CollisionSettings settings = new CollisionSettings(config);
return settings.density()
.map(density -> new CollisionPolicy(settings, density))
.collect(toSet());
}

@Override
public void record(long key) {
Object value = cache.getIfPresent(key);
if (value == null) {
if (trackedSize == maximumSize) {
policyStats.recordEviction();
trackedSize--;
}
cache.putIfAbsent(key, key);
policyStats.recordMiss();
trackedSize++;
} else {
policyStats.recordHit();
}
}

@Override
public PolicyStats stats() {
return policyStats;
}

enum Density { SPARSE, PACKED }

static final class CollisionSettings extends BasicSettings {
public CollisionSettings(Config config) {
super(config);
}
public int initCount() {
return config().getInt("collision.init-count");
}
public int bucketSize() {
return config().getInt("collision.bucket-size");
}
public double sparseFactor() {
return config().getDouble("collision.sparse-factor");
}
public boolean strictCapacity() {
return config().getBoolean("collision.strict-capacity");
}
public Stream<Density> density() {
return config().getStringList("collision.density").stream()
.map(denity -> Density.valueOf(denity.toUpperCase()));
}
}
}
17 changes: 15 additions & 2 deletions simulator/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,19 @@ caffeine.simulator {
"product.Ehcache3",
"product.Infinispan",
"product.ElasticSearch",

# Requires JDK9
#"product.Collision",
]

# The admission policy (opposite of eviction policy)
admission = [
"Always",
"TinyLfu",
]

# The membership filter implementation: Caffeine, Guava, AddThis
membership-filter = "caffeine"
membership-filter = "caffeine"

sampling {
# The random sample size
Expand Down Expand Up @@ -279,6 +282,16 @@ caffeine.simulator {
policy = "lfu"
}

collision {
init-count = 1
bucket-size = 16
sparse-factor = 5.0
strict-capacity = true

# Densities: Sparse, Packed
density = ["sparse"]
}

# files: reads from the trace file(s)
# synthetic: reads from a synthetic generator
source = "files"
Expand Down

0 comments on commit 260ec05

Please sign in to comment.