diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6dcf131488..3467b1b2c7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ asm = "9.7" auto-value = "1.11.0" awaitility = "4.2.1" -bcel = "6.9.0" +bcel = "6.10.0" bnd = "7.0.0" bouncycastle-jdk18on = "1.78.1" cache2k = "2.6.1.Final" @@ -13,18 +13,18 @@ coherence = "22.06.2" commons-collections4 = "4.4" commons-compress = "1.26.2" commons-io = "2.16.1" -commons-lang3 = "3.14.0" +commons-lang3 = "3.15.0" commons-math3 = "3.6.1" commons-text = "1.12.0" concurrentlinkedhashmap = "1.4.2" config = "1.4.3" coveralls = "2.12.2" -dependency-check = "10.0.2" +dependency-check = "10.0.3" eclipse-collections = "12.0.0.M3" ehcache3 = "3.10.8" -errorprone = "2.28.0" +errorprone = "2.29.2" errorprone-plugin = "4.0.1" -errorprone-support = "0.16.1" +errorprone-support = "0.17.0" expiring-map = "0.5.11" fast-filter = "1.0.2" fastutil = "8.5.13" @@ -36,8 +36,8 @@ forbidden-apis = "3.7" google-java-format = "1.22.0" guava = "33.2.1-jre" guice = "6.0.0" -h2 = "2.2.224" -hamcrest = "2.2" +h2 = "2.3.230" +hamcrest = "3.0-rc1" hazelcast = "5.3.7" httpclient = "4.5.14" idea = "1.1.8" @@ -63,7 +63,7 @@ jsoup = "1.18.1" junit-testng = "1.0.5" junit4 = "4.13.2" junit5 = "5.11.0-M2" -jvm-dependency-conflict-resolution = "2.1.1" +jvm-dependency-conflict-resolution = "2.1.2" kotlin = "2.0.0" lincheck = "2.32" mockito = "5.12.0" @@ -96,7 +96,7 @@ versions = "0.51.0" xz = "1.9" ycsb = "0.17.0" zero-allocation-hashing = "0.26ea0" -zstd = "1.5.6-3" +zstd = "1.5.6-4" [libraries] asm-bom = { module = "org.ow2.asm:asm-bom", version.ref = "asm" } diff --git a/gradle/plugins/src/main/kotlin/ProjectExtensions.kt b/gradle/plugins/src/main/kotlin/ProjectExtensions.kt index 103216de70..09f88e1b92 100644 --- a/gradle/plugins/src/main/kotlin/ProjectExtensions.kt +++ b/gradle/plugins/src/main/kotlin/ProjectExtensions.kt @@ -9,11 +9,16 @@ fun Project.version(major: Int, minor: Int, patch: Int, releaseBuild: Boolean) { version = "$major.$minor.$patch" + if (releaseBuild) "" else "-SNAPSHOT" } -fun Project.javaExecJvmArgs(): List { - val arguments = findProperty("jvmArgs") as String? +fun Project.defaultJvmArgs(): List { val jvmArgs = mutableListOf("-Xmx4g") + if (System.getenv("GRAALVM") == "true") { + jvmArgs += listOf( + "-XX:+UnlockExperimentalVMOptions", "-Dgraal.ShowConfiguration=info", + "-XX:+EnableJVMCI", "-XX:+UseJVMCICompiler", "-XX:+EagerJVMCI") + } + val arguments = findProperty("jvmArgs") as String? if (arguments != null) { - jvmArgs.addAll(arguments.split(",")) + jvmArgs += arguments.split(",") } return jvmArgs } @@ -30,13 +35,13 @@ fun isCI(): Boolean { val DisableStrongEncapsulationJvmArgs = listOf( "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED", "--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", "--add-opens", "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED", "--add-opens", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED") diff --git a/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts b/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts index 546fa54299..a757fa643d 100644 --- a/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts +++ b/gradle/plugins/src/main/kotlin/analyze/jmh.caffeine.gradle.kts @@ -30,6 +30,7 @@ jmh { iterations = 3 timeUnit = "s" + jvmArgs = defaultJvmArgs() failOnError = true forceGC = true fork = 1 @@ -37,14 +38,6 @@ jmh { resultsFile = layout.buildDirectory.file("reports/jmh/results.json") resultFormat = "json" - val jvmArguments = mutableListOf("-Xmx2G") - if (System.getenv("GRAALVM") == "true") { - jvmArguments += listOf( - "-XX:+UnlockExperimentalVMOptions", "-Dgraal.ShowConfiguration=info", - "-XX:+EnableJVMCI", "-XX:+UseJVMCICompiler", "-XX:+EagerJVMCI") - } - jvmArgs = jvmArguments - val includePattern: String? by project if (includePattern != null) { includes = listOf(includePattern) diff --git a/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts b/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts index 3b99a858d4..23f26299c2 100644 --- a/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts +++ b/gradle/plugins/src/main/kotlin/lifecycle/testing.caffeine.gradle.kts @@ -32,10 +32,7 @@ tasks.withType().configureEach { if ("debug" in systemProperties) { jvmArgs("-Xdebug", "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005") } - if (environment["GRAALVM"] == "true") { - jvmArgs("-XX:+UnlockExperimentalVMOptions", "-Dgraal.ShowConfiguration=info", - "-XX:+EnableJVMCI", "-XX:+UseJVMCICompiler", "-XX:+EagerJVMCI") - } + jvmArgs(defaultJvmArgs()) if (isCI()) { reports.junitXml.includeSystemOutLog = false reports.junitXml.includeSystemErrLog = false diff --git a/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts b/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts index 4470462fc6..c10088283b 100644 --- a/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts +++ b/gradle/plugins/src/main/kotlin/quality/errorprone.caffeine.gradle.kts @@ -111,6 +111,7 @@ fun enabledChecks() = listOf( "MissingDefault", "MixedArrayDimensions", "MissingDefault", + "MissingRuntimeRetention", "MockitoDoSetup", "MutableGuiceModule", "NoAllocation", diff --git a/simulator/build.gradle.kts b/simulator/build.gradle.kts index 7d4ef015e7..f23c4719ce 100644 --- a/simulator/build.gradle.kts +++ b/simulator/build.gradle.kts @@ -84,7 +84,7 @@ tasks.withType().configureEach { classpath(sourceSets["main"].runtimeClasspath) systemProperties(caffeineSystemProperties()) outputs.upToDateWhen { false } - jvmArgs(javaExecJvmArgs()) + jvmArgs(defaultJvmArgs()) } eclipse.classpath.file.beforeMerged { diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/Admission.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/Admission.java index 742e86da1e..b3eb4450c7 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/Admission.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/Admission.java @@ -15,11 +15,14 @@ */ package com.github.benmanes.caffeine.cache.simulator.admission; +import static java.util.Locale.US; + import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.UnaryOperator; +import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.clairvoyant.Clairvoyant; import com.github.benmanes.caffeine.cache.simulator.policy.PolicyStats; +import com.google.common.base.Enums; import com.typesafe.config.Config; /** @@ -29,15 +32,16 @@ */ @SuppressWarnings("ImmutableEnumChecker") public enum Admission { - ALWAYS((config, policyStats) -> Admittor.always(), UnaryOperator.identity()), - TINYLFU(TinyLfu::new, name -> name + "_TinyLfu"); + ALWAYS((config, policyStats) -> Admittor.always(), ""), + CLAIRVOYANT(Clairvoyant::new, "_Clairvoyant"), + TINYLFU(TinyLfu::new, "_TinyLfu"); private final BiFunction factory; - private final Function formatter; + private final String suffix; - Admission(BiFunction factory, UnaryOperator formatter) { - this.formatter = formatter; + Admission(BiFunction factory, String suffix) { this.factory = factory; + this.suffix = suffix; } /** @@ -48,11 +52,16 @@ public enum Admission { * @return an admission policy */ public Admittor from(Config config, PolicyStats policyStats) { + if (this == TINYLFU) { + var override = new BasicSettings(config).tinyLfu().sketch().toUpperCase(US); + return Enums.getIfPresent(Admission.class, override).or(this) + .factory.apply(config, policyStats); + } return factory.apply(config, policyStats); } /** Returns the policy's formatted name. */ public String format(String name) { - return formatter.apply(name); + return name + suffix; } } diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/TinyLfu.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/TinyLfu.java index 6d0c62f5eb..eceec74324 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/TinyLfu.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/TinyLfu.java @@ -15,6 +15,8 @@ */ package com.github.benmanes.caffeine.cache.simulator.admission; +import static java.util.Locale.US; + import java.util.Random; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; @@ -57,33 +59,6 @@ public TinyLfu(Config config, PolicyStats policyStats) { } } - private Frequency makeSketch(BasicSettings settings) { - String type = settings.tinyLfu().sketch(); - if (type.equalsIgnoreCase("count-min-4")) { - String reset = settings.tinyLfu().countMin4().reset(); - if (reset.equalsIgnoreCase("periodic")) { - return new PeriodicResetCountMin4(settings.config()); - } else if (reset.equalsIgnoreCase("incremental")) { - return new IncrementalResetCountMin4(settings.config()); - } else if (reset.equalsIgnoreCase("climber")) { - return new ClimberResetCountMin4(settings.config()); - } else if (reset.equalsIgnoreCase("indicator")) { - return new IndicatorResetCountMin4(settings.config()); - } else { - throw new IllegalStateException("Unknown reset type: " + reset); - } - } else if (type.equalsIgnoreCase("count-min-64")) { - return new CountMin64TinyLfu(settings.config()); - } else if (type.equalsIgnoreCase("random-table")) { - return new RandomRemovalFrequencyTable(settings.config()); - } else if (type.equalsIgnoreCase("tiny-table")) { - return new TinyCacheAdapter(settings.config()); - } else if (type.equalsIgnoreCase("perfect-table")) { - return new PerfectFrequency(settings.config()); - } - throw new IllegalStateException("Unknown sketch type: " + type); - } - public int frequency(long key) { return sketch.frequency(key); } @@ -107,4 +82,26 @@ public boolean admit(long candidateKey, long victimKey) { policyStats.recordRejection(); return false; } + + /** Returns the frequency histogram. */ + private static Frequency makeSketch(BasicSettings settings) { + String type = settings.tinyLfu().sketch(); + switch (type.toLowerCase(US)) { + case "count-min-4": { + String reset = settings.tinyLfu().countMin4().reset(); + switch (reset.toLowerCase(US)) { + case "climber": return new ClimberResetCountMin4(settings.config()); + case "periodic": return new PeriodicResetCountMin4(settings.config()); + case "indicator": return new IndicatorResetCountMin4(settings.config()); + case "incremental": return new IncrementalResetCountMin4(settings.config()); + default: throw new IllegalStateException("Unknown reset type: " + reset); + } + } + case "tiny-table": return new TinyCacheAdapter(settings.config()); + case "count-min-64": return new CountMin64TinyLfu(settings.config()); + case "perfect-table": return new PerfectFrequency(settings.config()); + case "random-table": return new RandomRemovalFrequencyTable(settings.config()); + default: throw new IllegalStateException("Unknown sketch type: " + type); + } + } } diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/clairvoyant/Clairvoyant.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/clairvoyant/Clairvoyant.java new file mode 100644 index 0000000000..84d629da1b --- /dev/null +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/admission/clairvoyant/Clairvoyant.java @@ -0,0 +1,112 @@ +/* + * Copyright 2024 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.admission.clairvoyant; + +import static com.google.common.base.Preconditions.checkState; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; + +import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admittor.KeyOnlyAdmittor; +import com.github.benmanes.caffeine.cache.simulator.policy.AccessEvent; +import com.github.benmanes.caffeine.cache.simulator.policy.PolicyStats; +import com.typesafe.config.Config; + +import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntPriorityQueue; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + +/** + * {@literal Bélády's} optimal page replacement policy applied as an admission policy by comparing + * the keys using their next access times. + * + * @author ben.manes@gmail.com (Ben Manes) + */ +public final class Clairvoyant implements KeyOnlyAdmittor { + private static final AtomicReference> snapshot = new AtomicReference<>(); + + private final Long2ObjectMap accessTimes; + private final PolicyStats policyStats; + + public Clairvoyant(Config config, PolicyStats policyStats) { + if (snapshot.get() == null) { + snapshot.set(readAccessTimes(new BasicSettings(config))); + } + accessTimes = new Long2ObjectOpenHashMap<>(snapshot.get().size()); + for (var entry : snapshot.get().long2ObjectEntrySet()) { + var times = new IntArrayFIFOQueue(entry.getValue().size()); + accessTimes.put(entry.getLongKey(), times); + entry.getValue().forEach(times::enqueue); + } + this.policyStats = policyStats; + } + + @Override + public void record(long key) { + if (snapshot.get() != null) { + snapshot.set(null); + } + + var times = accessTimes.get(key); + if (times == null) { + return; + } + times.dequeueInt(); + if (times.isEmpty()) { + accessTimes.remove(key); + } + } + + @Override + public boolean admit(long candidateKey, long victimKey) { + var candidateTime = nextAccessTime(candidateKey); + var victimTime = nextAccessTime(victimKey); + if (candidateTime > victimTime) { + policyStats.recordRejection(); + return false; + } + policyStats.recordAdmission(); + return true; + } + + private int nextAccessTime(long key) { + var times = accessTimes.get(key); + return ((times == null) || times.isEmpty()) ? Integer.MAX_VALUE : times.firstInt(); + } + + private static Long2ObjectMap readAccessTimes(BasicSettings settings) { + checkState(!settings.trace().isSynthetic(), "Synthetic traces cannot be predicted"); + var accessTimes = new Long2ObjectOpenHashMap(); + var trace = settings.trace().traceFiles().format() + .readFiles(settings.trace().traceFiles().paths()); + try (Stream events = trace.events()) { + int[] tick = { 0 }; + events.forEach(event -> { + var times = accessTimes.get(event.key()); + if (times == null) { + times = new IntArrayList(); + accessTimes.put(event.key(), times); + } + times.add(++tick[0]); + }); + } + return accessTimes; + } +} diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/WindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/WindowTinyLfuPolicy.java index f1b4aff641..989848cd75 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/WindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/WindowTinyLfuPolicy.java @@ -22,8 +22,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -70,7 +70,7 @@ public final class WindowTinyLfuPolicy implements KeyOnlyPolicy { public WindowTinyLfuPolicy(double percentMain, WindowTinyLfuSettings settings) { this.policyStats = new PolicyStats(name() + " (%.0f%%)", 100 * (1.0d - percentMain)); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.maximumSize = Math.toIntExact(settings.maximumSize()); int maxMain = (int) (maximumSize * percentMain); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/climbing/HillClimberWindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/climbing/HillClimberWindowTinyLfuPolicy.java index 42de0252f4..ef80f42816 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/climbing/HillClimberWindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/climbing/HillClimberWindowTinyLfuPolicy.java @@ -31,8 +31,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -89,7 +89,7 @@ public HillClimberWindowTinyLfuPolicy(HillClimberType strategy, double percentMa this.initialPercentMain = percentMain; this.policyStats = new PolicyStats(name() + " (%s %.0f%%)", strategy.name().toLowerCase(US), 100 * (1.0 - initialPercentMain)); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.climber = strategy.create(settings.config()); printSegmentSizes(); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackTinyLfuPolicy.java index a81b748212..4926d8931b 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackTinyLfuPolicy.java @@ -20,7 +20,8 @@ import java.util.Map; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; +import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; import com.github.benmanes.caffeine.cache.simulator.membership.Membership; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -46,7 +47,7 @@ public final class FeedbackTinyLfuPolicy implements KeyOnlyPolicy { private final Long2ObjectMap data; private final PolicyStats policyStats; - private final TinyLfu admittor; + private final Admittor admittor; private final int maximumSize; private final Node head; @@ -65,7 +66,7 @@ public FeedbackTinyLfuPolicy(Config config) { this.policyStats = new PolicyStats(name()); FeedbackTinyLfuSettings settings = new FeedbackTinyLfuSettings(config); this.maximumSize = Math.toIntExact(settings.maximumSize()); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.data = new Long2ObjectOpenHashMap<>(); this.head = new Node(); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackWindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackWindowTinyLfuPolicy.java index 3a9c775652..934959b537 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackWindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/feedback/FeedbackWindowTinyLfuPolicy.java @@ -24,7 +24,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; +import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; import com.github.benmanes.caffeine.cache.simulator.membership.Membership; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; @@ -51,7 +52,7 @@ public final class FeedbackWindowTinyLfuPolicy implements KeyOnlyPolicy { private final Long2ObjectMap data; private final PolicyStats policyStats; - private final TinyLfu admittor; + private final Admittor admittor; private final int maximumSize; private final Node headWindow; @@ -81,7 +82,7 @@ public final class FeedbackWindowTinyLfuPolicy implements KeyOnlyPolicy { public FeedbackWindowTinyLfuPolicy(double percentMain, FeedbackWindowTinyLfuSettings settings) { this.policyStats = new PolicyStats(name() + " (%.0f%%)", 100 * (1.0d - percentMain)); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.maximumSize = Math.toIntExact(settings.maximumSize()); int maxMain = (int) (maximumSize * percentMain); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/FullySegmentedWindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/FullySegmentedWindowTinyLfuPolicy.java index 4600368c83..1794e931ec 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/FullySegmentedWindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/FullySegmentedWindowTinyLfuPolicy.java @@ -22,8 +22,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -69,7 +69,7 @@ public FullySegmentedWindowTinyLfuPolicy( this.maxWindow = maximumSize - maxMain; this.maxMainProtected = (int) (maxMain * settings.percentMainProtected()); this.maxWindowProtected = (int) (maxWindow * settings.percentWindowProtected()); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.data = new Long2ObjectOpenHashMap<>(); this.headWindowProbation = new Node(); this.headWindowProtected = new Node(); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/LruWindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/LruWindowTinyLfuPolicy.java index a29310bd34..401d884b46 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/LruWindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/LruWindowTinyLfuPolicy.java @@ -22,8 +22,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -56,7 +56,7 @@ public final class LruWindowTinyLfuPolicy implements KeyOnlyPolicy { public LruWindowTinyLfuPolicy(double percentMain, LruWindowTinyLfuSettings settings) { this.policyStats = new PolicyStats(name() + " (%.0f%%)", 100 * (1.0d - percentMain)); int maximumSize = Math.toIntExact(settings.maximumSize()); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.maxMain = (int) (maximumSize * percentMain); this.data = new Long2ObjectOpenHashMap<>(); this.maxWindow = maximumSize - maxMain; diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/RandomWindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/RandomWindowTinyLfuPolicy.java index 592d69557b..c98be82fd7 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/RandomWindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/RandomWindowTinyLfuPolicy.java @@ -22,8 +22,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -55,7 +55,7 @@ public final class RandomWindowTinyLfuPolicy implements KeyOnlyPolicy { public RandomWindowTinyLfuPolicy(double percentMain, RandomWindowTinyLfuSettings settings) { policyStats = new PolicyStats(name() + " (%.0f%%)", 100 * (1.0d - percentMain)); maximumSize = Math.toIntExact(settings.maximumSize()); - admittor = new TinyLfu(settings.config(), policyStats); + admittor = Admission.TINYLFU.from(settings.config(), policyStats); random = new Random(settings.randomSeed()); data = new Long2ObjectOpenHashMap<>(); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/S4WindowTinyLfuPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/S4WindowTinyLfuPolicy.java index 1a8ef765fb..4b380f69ad 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/S4WindowTinyLfuPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/sketch/segment/S4WindowTinyLfuPolicy.java @@ -23,8 +23,8 @@ import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; +import com.github.benmanes.caffeine.cache.simulator.admission.Admission; import com.github.benmanes.caffeine.cache.simulator.admission.Admittor; -import com.github.benmanes.caffeine.cache.simulator.admission.TinyLfu; import com.github.benmanes.caffeine.cache.simulator.policy.Policy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.KeyOnlyPolicy; import com.github.benmanes.caffeine.cache.simulator.policy.Policy.PolicySpec; @@ -58,7 +58,7 @@ public final class S4WindowTinyLfuPolicy implements KeyOnlyPolicy { public S4WindowTinyLfuPolicy(double percentMain, S4WindowTinyLfuSettings settings) { this.policyStats = new PolicyStats(name() + " (%.0f%%)", 100 * (1.0d - percentMain)); - this.admittor = new TinyLfu(settings.config(), policyStats); + this.admittor = Admission.TINYLFU.from(settings.config(), policyStats); this.maximumSize = Math.toIntExact(settings.maximumSize()); this.maxMain = (int) (maximumSize * percentMain); this.maxWindow = maximumSize - maxMain; diff --git a/simulator/src/main/resources/reference.conf b/simulator/src/main/resources/reference.conf index 0a196a4c9a..04eae47eb6 100644 --- a/simulator/src/main/resources/reference.conf +++ b/simulator/src/main/resources/reference.conf @@ -113,6 +113,7 @@ caffeine.simulator { admission = [ Always, TinyLfu, + Clairvoyant, ] # The membership filter @@ -191,6 +192,8 @@ caffeine.simulator { tiny-lfu { # CountMinSketch: count-min-4 (4-bit), count-min-64 (64-bit) # Table: random-table, tiny-table, perfect-table + # Clairvoyant: next access times comparison + # Always: always admits (disablement) sketch = count-min-4 # If increments are conservative by only updating the minimum counters for CountMin sketches