Files
VoxelForge/Standalone/Source/StandaloneTlsProbe.h
T
Fr0zkaandClaude Opus 5.5 7770074503 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
2026-10-19 19:16:14 +02:00

208 lines
8.6 KiB
C++

#pragma once
#include "StandaloneWorkerThread.h"
#include "VoxelForgeCore/VoxelForgeCore.h"
#include <algorithm>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdio>
#include <cstdint>
#include <fstream>
#include <mutex>
#include <numeric>
#include <string>
#include <string_view>
#include <thread>
#include <vector>
#if defined(__linux__)
#include <unistd.h>
#include <sys/resource.h>
#endif
namespace StandaloneTlsProbe
{
#if defined(__linux__)
struct FMemorySample
{
std::uint64_t virtualKiB=0;
std::uint64_t residentKiB=0;
};
inline FMemorySample ReadMemory()
{
std::ifstream statm("/proc/self/statm");
std::uint64_t virtualPages=0,residentPages=0;
statm>>virtualPages>>residentPages;
const long pageSize=sysconf(_SC_PAGESIZE);
if(!statm||pageSize<=0)return {};
return {virtualPages*static_cast<std::uint64_t>(pageSize)/1024,
residentPages*static_cast<std::uint64_t>(pageSize)/1024};
}
inline int Run(int workerCount,std::string_view touchKind="none")
{
workerCount=std::clamp(workerCount,0,12);
VoxelForgeCore::WorldAssemblyRecipeV1 surfaceRecipe;
VoxelForgeCore::WorldAssemblyStratumPlanV1 surfacePlan;
VoxelForgeCore::Heightfield2D surfaceField(surfaceRecipe,surfacePlan);
if(touchKind=="surface-world")
{
VoxelForgeCore::WorldAssemblyBiomeProfileV1 biome;
biome.stableId=1;
surfaceRecipe.biomes.push_back(biome);
surfacePlan.strateIndex=0;
surfacePlan.topChunkZ=1;
surfacePlan.bottomChunkZ=-1;
surfaceField=VoxelForgeCore::Heightfield2D(surfaceRecipe,surfacePlan);
if(!surfaceField.isValid())
{
std::fprintf(stderr,"[TlsProbe] invalid synthetic SurfaceWorld cache probe input\n");
return 2;
}
}
VoxelForgeCore::FloatingIslandRecipeV1 islandRecipe;
VoxelForgeCore::FloatingIslandPlanV1 islandPlan;
for(std::uint32_t index=0;index<islandRecipe.primaryIslandCount;++index)
{
VoxelForgeCore::FloatingIslandAnchorV1 island;
island.stableId=index+1;
island.ordinal=index;
island.centerSubvoxels={static_cast<std::int64_t>(index)*64*256,0,0};
island.radiusSubvoxels=20*256;
island.topHalfSubvoxels=20*256;
island.topZSubvoxels=0;
island.bottomZSubvoxels=-80*256;
island.taperEndQ16=islandRecipe.taperEndMinimumQ16;
islandPlan.islands.push_back(island);
}
VoxelForgeCore::FloatingIslandFieldV1 islandField(islandRecipe,islandPlan);
if(touchKind=="floating-islands"&&!islandField.isValid())
{
std::fprintf(stderr,"[TlsProbe] invalid synthetic FloatingIslands cache probe input\n");
return 2;
}
std::mutex mutex;
std::condition_variable changed;
bool release=false;
bool touchRequested=false;
std::atomic<int> ready{0};
std::atomic<int> touchReady{0};
std::vector<FStandaloneWorkerThread> workers;
std::vector<long> startupMinorFaults(static_cast<std::size_t>(workerCount),0);
std::vector<long> firstTouchMinorFaults(static_cast<std::size_t>(workerCount),0);
std::vector<std::int64_t> checksums(static_cast<std::size_t>(workerCount),0);
workers.reserve(static_cast<std::size_t>(workerCount));
FMemorySample previous=ReadMemory();
std::printf("[TlsProbe] workers=0 create_ms=0.000 rss_kib=%llu rss_delta_kib=0 vms_kib=%llu stack_bytes=%zu\n",
static_cast<unsigned long long>(previous.residentKiB),
static_cast<unsigned long long>(previous.virtualKiB),
FStandaloneWorkerThread::StackSizeBytes);
for(int index=1;index<=workerCount;++index)
{
const auto start=std::chrono::steady_clock::now();
workers.emplace_back([&,index]
{
#if defined(__linux__)
rusage startupUsage{};
getrusage(RUSAGE_THREAD,&startupUsage);
startupMinorFaults[static_cast<std::size_t>(index-1)]=startupUsage.ru_minflt;
#endif
ready.fetch_add(1,std::memory_order_release);
changed.notify_all();
{
std::unique_lock lock(mutex);
changed.wait(lock,[&]{return touchRequested||release;});
}
if(touchRequested)
{
#if defined(__linux__)
rusage beforeTouch{};
rusage afterTouch{};
getrusage(RUSAGE_THREAD,&beforeTouch);
#endif
std::int64_t checksum=0;
if(touchKind=="surface-world")
{
for(int sample=0;sample<4;++sample)
checksum+=surfaceField.point((index*4+sample)*256,0,0).densitySubvoxels;
}
else if(touchKind=="floating-islands")
{
for(int sample=0;sample<4;++sample)
checksum+=islandField.densitySubvoxels(
(index*4+sample)*256,0,-20*256);
}
checksums[static_cast<std::size_t>(index-1)]=checksum;
#if defined(__linux__)
getrusage(RUSAGE_THREAD,&afterTouch);
firstTouchMinorFaults[static_cast<std::size_t>(index-1)]=
afterTouch.ru_minflt-beforeTouch.ru_minflt;
#endif
touchReady.fetch_add(1,std::memory_order_release);
changed.notify_all();
}
std::unique_lock lock(mutex);
changed.wait(lock,[&]{return release;});
});
{
std::unique_lock lock(mutex);
changed.wait(lock,[&]{return ready.load(std::memory_order_acquire)>=index;});
}
const double createMs=std::chrono::duration<double,std::milli>(
std::chrono::steady_clock::now()-start).count();
const FMemorySample current=ReadMemory();
const std::int64_t rssDelta=static_cast<std::int64_t>(current.residentKiB)
-static_cast<std::int64_t>(previous.residentKiB);
std::printf("[TlsProbe] workers=%d create_ms=%.3f rss_kib=%llu rss_delta_kib=%lld vms_kib=%llu\n",
index,createMs,static_cast<unsigned long long>(current.residentKiB),
static_cast<long long>(rssDelta),static_cast<unsigned long long>(current.virtualKiB));
previous=current;
}
const FMemorySample beforeTouch=ReadMemory();
std::printf("[TlsProbeTouch] kind=%.*s rss_before_kib=%llu\n",
static_cast<int>(touchKind.size()),touchKind.data(),
static_cast<unsigned long long>(beforeTouch.residentKiB));
if(touchKind!="none")
{
{
std::lock_guard lock(mutex);
touchRequested=true;
}
changed.notify_all();
{
std::unique_lock lock(mutex);
changed.wait(lock,[&]{return touchReady.load(std::memory_order_acquire)==workerCount;});
}
const FMemorySample afterTouch=ReadMemory();
std::printf("[TlsProbeTouch] kind=%.*s rss_after_kib=%llu rss_delta_kib=%lld checksum_sum=%lld\n",
static_cast<int>(touchKind.size()),touchKind.data(),
static_cast<unsigned long long>(afterTouch.residentKiB),
static_cast<long long>(static_cast<std::int64_t>(afterTouch.residentKiB)
-static_cast<std::int64_t>(beforeTouch.residentKiB)),
static_cast<long long>(std::accumulate(checksums.begin(),checksums.end(),std::int64_t{0})));
for(int index=0;index<workerCount;++index)
std::printf("[TlsProbeTouch] worker=%d startup_minor_faults=%ld first_touch_minor_faults=%ld\n",
index+1,startupMinorFaults[static_cast<std::size_t>(index)],
firstTouchMinorFaults[static_cast<std::size_t>(index)]);
}
{
std::lock_guard lock(mutex);
release=true;
}
changed.notify_all();
for(FStandaloneWorkerThread& worker:workers)worker.join();
std::printf("[TlsProbe] status=PASS threads_joined=%d\n",workerCount);
return 0;
}
#else
inline int Run(int,std::string_view="none")
{
std::fprintf(stderr,"TLS probe is Linux-only.\n");
return 2;
}
#endif
}