perf(server): generate chunk baselines outside the cache lock
This commit is contained in:
parent
1d041e035e
commit
95c798954c
|
|
@ -26,8 +26,12 @@ impl ChunkCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the baseline for `pos`, generating and caching it on a miss.
|
/// Returns the baseline for `pos`, generating and caching it on a miss.
|
||||||
|
///
|
||||||
|
/// Generation runs outside the lock, so concurrent callers do not serialise on a cache miss. Two callers racing on the same position may each generate a baseline; generation is deterministic and side-effect-free, so the duplicated work is redundant rather than incorrect, and is far cheaper than serialising every miss behind the store.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_or_generate(&self, pos: ChunkPos, generator: &VoxelGenerator) -> Chunk {
|
pub fn get_or_generate(&self, pos: ChunkPos, generator: &VoxelGenerator) -> Chunk {
|
||||||
|
// Probe under the lock, then release it before generating.
|
||||||
|
{
|
||||||
// A poisoned lock cannot yield a usable cache; recovering the guard lets generation proceed rather than propagating a panic across every worker that shares this cache.
|
// A poisoned lock cannot yield a usable cache; recovering the guard lets generation proceed rather than propagating a panic across every worker that shares this cache.
|
||||||
let mut guard = self
|
let mut guard = self
|
||||||
.inner
|
.inner
|
||||||
|
|
@ -36,8 +40,16 @@ impl ChunkCache {
|
||||||
if let Some(hit) = guard.get(&pos) {
|
if let Some(hit) = guard.get(&pos) {
|
||||||
return hit.clone();
|
return hit.clone();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let chunk = generator.generate_chunk(pos);
|
let chunk = generator.generate_chunk(pos);
|
||||||
guard.put(pos, chunk.clone());
|
|
||||||
|
// Retake the lock only to publish. A concurrent caller may have inserted the same position in the meantime; overwriting is harmless because both baselines are identical.
|
||||||
|
self.inner
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.put(pos, chunk.clone());
|
||||||
|
|
||||||
chunk
|
chunk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue