Recent bake entry fast path

- Facade reads reuse the thread's last chunk entry instead of probing the bake map
- Stores and full-chunk fills refresh that entry from the map
- Surface lattice lookups reuse the previous point's cell indices
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-21 23:48:07 -04:00
1 parent 2bfa9c4528
commit fa996a2e24
2 files changed
+69 -10

No files matched your search

@@ -10,6 +10,7 @@ public final class ChunkBakeCache implements BakeCache {
private static final ThreadLocal<int[]> SPARSE = ThreadLocal.withInitial(() -> new int[1]);
private final PlaneSource source;
private final ThreadLocal<Recent> recent = ThreadLocal.withInitial(Recent::new);
private volatile ConcurrentClockCache<ChunkPlanes> entries;
public ChunkBakeCache(PlaneSource source, int capacityChunks) {
@@ -43,7 +44,9 @@ public final class ChunkBakeCache implements BakeCache {
}
public void clear() {
entries.clear();
ConcurrentClockCache<ChunkPlanes> current = entries;
entries = new ConcurrentClockCache<>(current.capacity());
current.clear();
}
public long[] census() {
@@ -71,8 +74,22 @@ public final class ChunkBakeCache implements BakeCache {
}
public ChunkPlanes.Plane planeIfPresent(BakePlane plane, int chunkX, int chunkZ) {
ChunkPlanes planes = entries.get(key(chunkX, chunkZ));
return planes == null ? null : planes.planeIfPresent(plane);
long key = key(chunkX, chunkZ);
Recent last = recent.get();
ConcurrentClockCache<ChunkPlanes> current = entries;
ChunkPlanes planes;
if (last.key == key && last.entries == current) {
planes = last.planes;
} else {
planes = current.get(key);
if (planes == null) {
return null;
}
last.key = key;
last.planes = planes;
last.entries = current;
}
return planes.planeIfPresent(plane);
}
public ChunkPlanes.Plane plane(BakePlane plane, int chunkX, int chunkZ) {
@@ -80,7 +97,7 @@ public final class ChunkBakeCache implements BakeCache {
}
public Object complete(BakePlane plane, int chunkX, int chunkZ) {
return planes(chunkX, chunkZ).complete(plane, source);
return remembered(chunkX, chunkZ).complete(plane, source);
}
public boolean memoAllowed() {
@@ -91,14 +108,26 @@ public final class ChunkBakeCache implements BakeCache {
if (revision != ProvisionalSampling.revision()) {
return;
}
planes(blockX >> 4, blockZ >> 4).plane(plane).storeDouble(((blockZ & 15) << 4) | (blockX & 15), value);
remembered(blockX >> 4, blockZ >> 4).plane(plane).storeDouble(((blockZ & 15) << 4) | (blockX & 15), value);
}
public void storeObject(BakePlane plane, int blockX, int blockZ, Object value, long revision) {
if (revision != ProvisionalSampling.revision()) {
return;
}
planes(blockX >> 4, blockZ >> 4).plane(plane).storeObject(((blockZ & 15) << 4) | (blockX & 15), value);
remembered(blockX >> 4, blockZ >> 4).plane(plane).storeObject(((blockZ & 15) << 4) | (blockX & 15), value);
}
private ChunkPlanes remembered(int chunkX, int chunkZ) {
ConcurrentClockCache<ChunkPlanes> current = entries;
long key = key(chunkX, chunkZ);
ChunkPlanes existing = current.get(key);
ChunkPlanes planes = existing != null ? existing : current.putIfAbsent(key, new ChunkPlanes(chunkX, chunkZ));
Recent last = recent.get();
last.key = key;
last.planes = planes;
last.entries = current;
return planes;
}
public static <T> T sparse(Supplier<T> action) {
@@ -125,4 +154,10 @@ public final class ChunkBakeCache implements BakeCache {
public static long key(int chunkX, int chunkZ) {
return ((long) chunkX << 32) ^ (chunkZ & 0xffffffffL);
}
private static final class Recent {
private long key;
private ChunkPlanes planes;
private ConcurrentClockCache<ChunkPlanes> entries;
}
}
@@ -69,6 +69,12 @@ public final class GeneratorProgram {
double[] fractionZ = scratch.buffer(count);
scratch.clearLattice(count * 4);
int detailed = 0;
double previousX = Double.NaN;
double previousZ = Double.NaN;
int cellNorthWest = -1;
int cellNorthEast = -1;
int cellSouthWest = -1;
int cellSouthEast = -1;
for (int index = 0; index < count; index++) {
double lowerX = Math.floor(xs[index] / SURFACE_GRID) * SURFACE_GRID;
double lowerZ = Math.floor(zs[index] / SURFACE_GRID) * SURFACE_GRID;
@@ -76,10 +82,28 @@ public final class GeneratorProgram {
double dz = (zs[index] - lowerZ) / SURFACE_GRID;
fractionX[index] = dx;
fractionZ[index] = dz;
northWest[index] = scratch.lattice(lowerX, lowerZ);
northEast[index] = dx == 0D ? -1 : scratch.lattice(lowerX + SURFACE_GRID, lowerZ);
southWest[index] = dz == 0D ? -1 : scratch.lattice(lowerX, lowerZ + SURFACE_GRID);
southEast[index] = dx == 0D || dz == 0D ? -1 : scratch.lattice(lowerX + SURFACE_GRID, lowerZ + SURFACE_GRID);
if (Double.doubleToRawLongBits(lowerX) != Double.doubleToRawLongBits(previousX)
|| Double.doubleToRawLongBits(lowerZ) != Double.doubleToRawLongBits(previousZ)) {
previousX = lowerX;
previousZ = lowerZ;
cellNorthWest = scratch.lattice(lowerX, lowerZ);
cellNorthEast = -1;
cellSouthWest = -1;
cellSouthEast = -1;
}
if (dx != 0D && cellNorthEast < 0) {
cellNorthEast = scratch.lattice(lowerX + SURFACE_GRID, lowerZ);
}
if (dz != 0D && cellSouthWest < 0) {
cellSouthWest = scratch.lattice(lowerX, lowerZ + SURFACE_GRID);
}
if (dx != 0D && dz != 0D && cellSouthEast < 0) {
cellSouthEast = scratch.lattice(lowerX + SURFACE_GRID, lowerZ + SURFACE_GRID);
}
northWest[index] = cellNorthWest;
northEast[index] = dx == 0D ? -1 : cellNorthEast;
southWest[index] = dz == 0D ? -1 : cellSouthWest;
southEast[index] = dx == 0D || dz == 0D ? -1 : cellSouthEast;
if (dx != 0D || dz != 0D) {
detailed++;
}