Clang -ffp-contract=on/fast and GCC's default (fast) all change the density hash on the L1 view; contraction off reproduces L1 (= Windows S13) at W1/W12. Seed sweep: 48 FloatingIslands seeds and 14 effective SurfaceWorld seeds (34 of 48 fell on a seed-independent cube) match across Clang/GCC and W1/W12. Standalone gains --seed/--recipe/--render-distance-chunks (viewer + headless) and a Windows replay script. Linux standalone workers get 32 MiB pthread stacks (TLS is 17.3 MiB/thread), so no external stack limit is needed. No Core or world-output change; MSVC compile unverified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
96 lines
3.2 KiB
C++
96 lines
3.2 KiB
C++
#pragma once
|
|
|
|
#include "StandaloneWorkerThread.h"
|
|
|
|
#include <algorithm>
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <cstdio>
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#if defined(__linux__)
|
|
#include <unistd.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)
|
|
{
|
|
workerCount=std::clamp(workerCount,0,12);
|
|
std::mutex mutex;
|
|
std::condition_variable changed;
|
|
bool release=false;
|
|
std::atomic<int> ready{0};
|
|
std::vector<FStandaloneWorkerThread> workers;
|
|
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([&]
|
|
{
|
|
ready.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;
|
|
}
|
|
{
|
|
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::fprintf(stderr,"TLS probe is Linux-only.\n");
|
|
return 2;
|
|
}
|
|
#endif
|
|
}
|