-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a clairvoyant admission policy to the simulator
Like Bélády's optimal policy for eviction, this estimates the upper bound for an admission policy by using future knowledge to make the best decision. The candidate entry is only admitted if its next access time is less than the victim's. While the optimal replacement policy is able to dictate the working set, the optimal admission policy is only able to advise whether to keep the given candidate or victim entry. Thus, the eviction policy's choices may result in a sequence where a more naive admission policy outperforms the clairvoyant one. The intent is to show the upper bounds of an adaptive admission policy based on its best guess rather than the upper bound of the overall cache hit rate.
- Loading branch information
Showing
18 changed files
with
199 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
.../java/com/github/benmanes/caffeine/cache/simulator/admission/clairvoyant/Clairvoyant.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [email protected] (Ben Manes) | ||
*/ | ||
public final class Clairvoyant implements KeyOnlyAdmittor { | ||
private static final AtomicReference<Long2ObjectMap<IntList>> snapshot = new AtomicReference<>(); | ||
|
||
private final Long2ObjectMap<IntPriorityQueue> 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<IntList> readAccessTimes(BasicSettings settings) { | ||
checkState(!settings.trace().isSynthetic(), "Synthetic traces cannot be predicted"); | ||
var accessTimes = new Long2ObjectOpenHashMap<IntList>(); | ||
var trace = settings.trace().traceFiles().format() | ||
.readFiles(settings.trace().traceFiles().paths()); | ||
try (Stream<AccessEvent> 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; | ||
} | ||
} |
Oops, something went wrong.