#pragma once #include "StandaloneWorkerThread.h" #include "VoxelForgeCore/VoxelForgeCore.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__linux__) #include #include #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(pageSize)/1024, residentPages*static_cast(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(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 ready{0}; std::atomic touchReady{0}; std::vector workers; std::vector startupMinorFaults(static_cast(workerCount),0); std::vector firstTouchMinorFaults(static_cast(workerCount),0); std::vector checksums(static_cast(workerCount),0); workers.reserve(static_cast(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(previous.residentKiB), static_cast(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(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(index-1)]=checksum; #if defined(__linux__) getrusage(RUSAGE_THREAD,&afterTouch); firstTouchMinorFaults[static_cast(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( std::chrono::steady_clock::now()-start).count(); const FMemorySample current=ReadMemory(); const std::int64_t rssDelta=static_cast(current.residentKiB) -static_cast(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(current.residentKiB), static_cast(rssDelta),static_cast(current.virtualKiB)); previous=current; } const FMemorySample beforeTouch=ReadMemory(); std::printf("[TlsProbeTouch] kind=%.*s rss_before_kib=%llu\n", static_cast(touchKind.size()),touchKind.data(), static_cast(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(touchKind.size()),touchKind.data(), static_cast(afterTouch.residentKiB), static_cast(static_cast(afterTouch.residentKiB) -static_cast(beforeTouch.residentKiB)), static_cast(std::accumulate(checksums.begin(),checksums.end(),std::int64_t{0}))); for(int index=0;index(index)], firstTouchMinorFaults[static_cast(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 }