From 228f29d4b5df63433802820472da9fade60ef723 Mon Sep 17 00:00:00 2001 From: leventov Date: Fri, 2 Oct 2015 10:59:36 +0300 Subject: [PATCH] More random walk in OldDeletedEntriesCleanup --- .../map/OldDeletedEntriesCleanup.java | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java index 44c324d0a..fbdf70d63 100644 --- a/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java +++ b/src/main/java/net/openhft/chronicle/map/OldDeletedEntriesCleanup.java @@ -23,17 +23,18 @@ import net.openhft.chronicle.hash.replication.TimeProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.function.Predicate; public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate { private static final Logger LOG = LoggerFactory.getLogger(OldDeletedEntriesCleanup.class); - private static final int PRIME_1 = 1_000_003, PRIME_2 = 999_983; - private final ReplicatedChronicleMap map; private final long timeout; - private final int step; + private final int[] segmentsPermutation; + private final int[] inverseSegmentsPermutation; private volatile boolean shutdown; private long prevSegment0ScanStart = -1; private long removedCompletely; @@ -41,8 +42,8 @@ public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate< public OldDeletedEntriesCleanup(ReplicatedChronicleMap map, long timeout) { this.map = map; this.timeout = timeout; - // step primality guarantees perfect segment permutation - step = map.segments() != PRIME_1 ? PRIME_1 : PRIME_2; + segmentsPermutation = randomPermutation(map.segments()); + inverseSegmentsPermutation = inversePermutation(segmentsPermutation); } @Override @@ -81,7 +82,7 @@ public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate< removedCompletely = 0; if (((ReplicatedHashSegmentContext) context) .forEachSegmentReplicableEntryWhile(this)) { - segmentIndex = (segmentIndex + step) % map.segments(); + segmentIndex = nextSegmentIndex(segmentIndex); map.globalMutableState.setCurrentCleanupSegmentIndex(segmentIndex); } } @@ -108,4 +109,39 @@ public class OldDeletedEntriesCleanup implements Runnable, Closeable, Predicate< public void close() { shutdown = true; } + + private int nextSegmentIndex(int segmentIndex) { + int permutationIndex = inverseSegmentsPermutation[segmentIndex]; + int nextPermutationIndex = (permutationIndex + 1) % map.segments(); + return segmentsPermutation[nextPermutationIndex]; + } + + private static int[] randomPermutation(int n) { + int[] a = new int[n]; + for (int i = 0; i < n; i++) { + a[i] = i; + } + shuffle(a); + return a; + } + + // Implementing Fisher–Yates shuffle + private static void shuffle(int[] a) { + Random rnd = ThreadLocalRandom.current(); + for (int i = a.length - 1; i > 0; i--) { + int index = rnd.nextInt(i + 1); + int e = a[index]; + a[index] = a[i]; + a[i] = e; + } + } + + private static int[] inversePermutation(int[] permutation) { + int n = permutation.length; + int[] inverse = new int[n]; + for (int i = 0; i < n; i++) { + inverse[permutation[i]] = i; + } + return inverse; + } }