wip(assembler): round L4 -- lazy per-thread caches: 17.3 MiB -> 43 KiB per thread, view 7% faster
VoxelForgeCoreThreadLocal::FLazy<T> (new public header ThreadLocalStorage.h) makes every large thread_local cache a pointer that heap-allocates on that thread's first use (still worker-private, lock-free). Static TLS 17.33 MiB -> 43 KiB (initialised image 5.8 MiB -> 21 KiB); worker start 5.2 -> 0.12 ms; idle worker RSS 17.7 MiB -> 52 KiB. Linux workers back to 8 MiB stacks. World unchanged (L1 hashes Clang off/GCC default, W1/W12; FloatingIslands seed 0). Reviewer interleaved W12: 2.256 -> 2.091 s. MSVC/UBT not compiled here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ED33VnqepD4YY6gDAAA832
This commit is contained in:
1 parent
046f2af495
commit
7770074503
15 files changed
+361
-48
No files matched your search
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "VoxelForgeCore/ThreadLocalStorage.h"
|
||||
#include "Json.h"
|
||||
#include "VoxelForgeCore/VoxelForgeCore.h"
|
||||
|
||||
@@ -1367,9 +1368,10 @@ namespace world_assembly_detail
|
||||
// qui partagent les bits faibles du hash.
|
||||
constexpr std::size_t HeightfieldColumnCacheWays=4;
|
||||
constexpr std::size_t HeightfieldColumnCacheSetCount=65536/HeightfieldColumnCacheWays;
|
||||
inline thread_local std::array<HeightfieldColumnCacheEntry, 65536> HeightfieldColumnCache{};
|
||||
inline thread_local std::array<std::uint8_t, HeightfieldColumnCacheSetCount>
|
||||
HeightfieldColumnCacheNextWay{};
|
||||
inline thread_local VoxelForgeCoreThreadLocal::FLazy<
|
||||
std::array<HeightfieldColumnCacheEntry, 65536>> HeightfieldColumnCache;
|
||||
inline thread_local VoxelForgeCoreThreadLocal::FLazy<
|
||||
std::array<std::uint8_t, HeightfieldColumnCacheSetCount>> HeightfieldColumnCacheNextWay;
|
||||
inline thread_local HeightfieldColumnCacheStats HeightfieldColumnStats{};
|
||||
inline thread_local bool HeightfieldColumnCacheLegacyDirectMapped=false;
|
||||
|
||||
@@ -1504,6 +1506,8 @@ namespace world_assembly_detail
|
||||
inline HeightfieldPointSample CachedColumn(const WorldAssemblyRecipeV1& recipe,
|
||||
const WorldAssemblyStratumPlanV1& plan,std::int64_t x,std::int64_t y)
|
||||
{
|
||||
auto& cache=HeightfieldColumnCache.Get();
|
||||
auto& nextWay=HeightfieldColumnCacheNextWay.Get();
|
||||
HeightfieldColumnCacheEntry* replacement=nullptr;
|
||||
if(HeightfieldColumnCacheLegacyDirectMapped)
|
||||
{
|
||||
@@ -1513,8 +1517,7 @@ namespace world_assembly_detail
|
||||
^std::rotl(static_cast<std::uint64_t>(y)*0xC2B2AE3D27D4EB4Full,23)
|
||||
^static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&recipe))
|
||||
^std::rotl(static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(&plan)),41);
|
||||
replacement=&HeightfieldColumnCache[static_cast<std::size_t>(mixed)
|
||||
&(HeightfieldColumnCache.size()-1)];
|
||||
replacement=&cache[static_cast<std::size_t>(mixed)&(cache.size()-1)];
|
||||
if(replacement->recipe==&recipe&&replacement->plan==&plan
|
||||
&&replacement->recipeHash==recipe.contentHash
|
||||
&&replacement->planHash==plan.contentHash&&replacement->x==x&&replacement->y==y)
|
||||
@@ -1528,7 +1531,7 @@ namespace world_assembly_detail
|
||||
std::size_t replacementWay=HeightfieldColumnCacheWays;
|
||||
for(std::size_t way=0;way<HeightfieldColumnCacheWays;++way)
|
||||
{
|
||||
auto& candidate=HeightfieldColumnCache[first+way];
|
||||
auto& candidate=cache[first+way];
|
||||
if(candidate.recipe==&recipe&&candidate.plan==&plan
|
||||
&&candidate.recipeHash==recipe.contentHash&&candidate.planHash==plan.contentHash
|
||||
&&candidate.x==x&&candidate.y==y)
|
||||
@@ -1539,11 +1542,11 @@ namespace world_assembly_detail
|
||||
if(replacementWay==HeightfieldColumnCacheWays)
|
||||
{
|
||||
++HeightfieldColumnStats.columnConflictMisses;
|
||||
replacementWay=HeightfieldColumnCacheNextWay[set];
|
||||
replacementWay=nextWay[set];
|
||||
}
|
||||
HeightfieldColumnCacheNextWay[set]=static_cast<std::uint8_t>(
|
||||
nextWay[set]=static_cast<std::uint8_t>(
|
||||
(replacementWay+1)%HeightfieldColumnCacheWays);
|
||||
replacement=&HeightfieldColumnCache[first+replacementWay];
|
||||
replacement=&cache[first+replacementWay];
|
||||
}
|
||||
auto& entry=*replacement;
|
||||
const auto start=std::chrono::steady_clock::now();
|
||||
@@ -2036,9 +2039,9 @@ void Heightfield2D::resetThreadColumnCacheStats(bool captureCoordinates, bool cl
|
||||
// Les sondes de mesure peuvent vider les entrees d'une tuile avant de comparer deux grilles.
|
||||
if(clearCache)
|
||||
{
|
||||
world_assembly_detail::HeightfieldColumnCache.fill(
|
||||
world_assembly_detail::HeightfieldColumnCache.Get().fill(
|
||||
world_assembly_detail::HeightfieldColumnCacheEntry{});
|
||||
world_assembly_detail::HeightfieldColumnCacheNextWay.fill(0);
|
||||
world_assembly_detail::HeightfieldColumnCacheNextWay.Get().fill(0);
|
||||
}
|
||||
auto& Stats=world_assembly_detail::HeightfieldColumnStats;
|
||||
world_assembly_detail::HeightfieldColumnOctaveDrop=octaveDrop;
|
||||
|
||||
Reference in new issue
Block a user