mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-11-01 17:00:26 +00:00
Fixed lattice eviction race
- Lattice eviction sorts a snapshot of tile access stamps - Concurrent tile use during eviction no longer breaks the sort - Test covers eviction under concurrent fills
This commit is contained in:
1 parent
6ceda7c53b
commit
618bb28591
2 files changed
+44
-10
No files matched your search
@@ -138,19 +138,19 @@ public final class HeightLattice {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<Map.Entry<Long, Tile>> idle = new ArrayList<>(tiles.size());
|
||||
List<IdleTile> idle = new ArrayList<>(tiles.size());
|
||||
for (Map.Entry<Long, Tile> entry : tiles.entrySet()) {
|
||||
if (entry.getValue().pending.get() == 0) {
|
||||
idle.add(entry);
|
||||
}
|
||||
}
|
||||
idle.sort(Comparator.comparingLong(entry -> entry.getValue().used));
|
||||
int target = capacityTiles - (capacityTiles >> 3);
|
||||
for (int index = 0; index < idle.size() && tiles.size() > target; index++) {
|
||||
Map.Entry<Long, Tile> entry = idle.get(index);
|
||||
Tile tile = entry.getValue();
|
||||
if (tile.pending.get() == 0) {
|
||||
tiles.remove(entry.getKey(), tile);
|
||||
idle.add(new IdleTile(entry.getKey(), tile, tile.used));
|
||||
}
|
||||
}
|
||||
idle.sort(Comparator.comparingLong(IdleTile::used));
|
||||
int target = capacityTiles - (capacityTiles >> 3);
|
||||
for (int index = 0; index < idle.size() && tiles.size() > target; index++) {
|
||||
IdleTile candidate = idle.get(index);
|
||||
if (candidate.tile().pending.get() == 0) {
|
||||
tiles.remove(candidate.key(), candidate.tile());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@@ -386,6 +386,9 @@ public final class HeightLattice {
|
||||
int cellZ(int index);
|
||||
}
|
||||
|
||||
private record IdleTile(Long key, Tile tile, long used) {
|
||||
}
|
||||
|
||||
private record Span(int cellX0, int cellZ0, int width, int stride) implements Nodes {
|
||||
@Override
|
||||
public int cellX(int index) {
|
||||
|
||||
@@ -100,6 +100,37 @@ public class HeightLatticeTest {
|
||||
assertEquals(DISTINCT_ACROSS_NINE, source.samples());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictionToleratesConcurrentTileUse() throws Exception {
|
||||
HeightLattice lattice = new HeightLattice(new CountingSource(), 1, false, 96 * 1024);
|
||||
int threads = 12;
|
||||
CyclicBarrier start = new CyclicBarrier(threads);
|
||||
ExecutorService pool = Executors.newFixedThreadPool(threads);
|
||||
try {
|
||||
List<Future<Void>> results = new ArrayList<>();
|
||||
for (int thread = 0; thread < threads; thread++) {
|
||||
long seed = 31L * thread + 7L;
|
||||
Callable<Void> task = () -> {
|
||||
Random random = new Random(seed);
|
||||
HydrologySampleBuffer out = new HydrologySampleBuffer(4);
|
||||
start.await();
|
||||
for (int fill = 0; fill < 40_000; fill++) {
|
||||
int tileX = random.nextInt(24);
|
||||
int tileZ = random.nextInt(24);
|
||||
lattice.fill(tileX * 32 + random.nextInt(31), tileZ * 32 + random.nextInt(31), 2, 2, out);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
results.add(pool.submit(task));
|
||||
}
|
||||
for (Future<Void> result : results) {
|
||||
result.get(120, TimeUnit.SECONDS);
|
||||
}
|
||||
} finally {
|
||||
pool.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsBitIdenticalValues() {
|
||||
HeightLattice full = new HeightLattice(new CountingSource(), 8, false, 1 << 16);
|
||||
|
||||
Reference in new issue
Block a user