fixed windows dataset not being shared across threads
This commit is contained in:
@@ -1180,7 +1180,9 @@ struct RandomXDatasetManager {
|
||||
|
||||
// Creates a per-thread VM using the shared dataset.
|
||||
// Caller must hold a shared lock on datasetMtx.
|
||||
// The VM itself is small (~2MB scratchpad) - the 2GB dataset is shared via pointer.
|
||||
// The VM itself is small (~2MB scratchpad + ~84KB JIT code) — the ~2GB dataset is shared via pointer.
|
||||
// VMs should be created ONCE per thread and reused across blocks to avoid
|
||||
// heap fragmentation on Windows (repeated 2MB alloc/free causes address-space bloat).
|
||||
randomx_vm *CreateVM() {
|
||||
static std::atomic<int> vmCount{0};
|
||||
LogProcessMemory("before CreateVM");
|
||||
@@ -1188,8 +1190,9 @@ struct RandomXDatasetManager {
|
||||
if (vm != nullptr) {
|
||||
int id = ++vmCount;
|
||||
uint8_t *datasetMemory = (uint8_t*)randomx_get_dataset_memory(dataset);
|
||||
LogPrintf("RandomXDatasetManager: VM #%d created - VM at %p, shared dataset memory at %p\n",
|
||||
LogPrintf("RandomXDatasetManager: VM #%d created — VM at %p, shared dataset at %p\n",
|
||||
id, (void*)vm, (void*)datasetMemory);
|
||||
LogPrintf(" Per-thread overhead: ~2MB scratchpad + ~84KB JIT (dataset NOT copied)\n");
|
||||
LogProcessMemory("after CreateVM");
|
||||
}
|
||||
return vm;
|
||||
@@ -1343,14 +1346,24 @@ void static RandomXMiner()
|
||||
rxdebug("%s: updated shared dataset with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str());
|
||||
}
|
||||
|
||||
// Create a per-thread VM that uses the shared dataset (read-only, thread-safe)
|
||||
// Create a per-thread VM once and reuse across blocks.
|
||||
// The VM just stores a pointer to the shared dataset — the pointer
|
||||
// remains valid across key changes since UpdateKey rebuilds the dataset
|
||||
// contents in-place without reallocating. Reusing the VM avoids
|
||||
// repeated 2MB scratchpad + 84KB JIT alloc/free churn that causes
|
||||
// Windows heap fragmentation and apparent memory growth per thread.
|
||||
if (myVM == nullptr) {
|
||||
// First iteration: acquire shared lock briefly to create VM
|
||||
boost::shared_lock<boost::shared_mutex> initLock(g_rxDatasetManager->datasetMtx);
|
||||
myVM = g_rxDatasetManager->CreateVM();
|
||||
if (myVM == nullptr) {
|
||||
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Acquire shared lock to prevent dataset rebuild while we're hashing
|
||||
boost::shared_lock<boost::shared_mutex> datasetLock(g_rxDatasetManager->datasetMtx);
|
||||
myVM = g_rxDatasetManager->CreateVM();
|
||||
if(myVM == NULL) {
|
||||
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
||||
return;
|
||||
}
|
||||
//fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
|
||||
#ifdef ENABLE_WALLET
|
||||
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0);
|
||||
@@ -1576,17 +1589,8 @@ void static RandomXMiner()
|
||||
pblock->nBits = savebits;
|
||||
}
|
||||
|
||||
rxdebug("%s: going to destroy rx VM\n");
|
||||
if (myVM != nullptr) {
|
||||
randomx_destroy_vm(myVM);
|
||||
myVM = nullptr;
|
||||
LogPrintf("RandomXMiner: destroyed VM after inner loop\n");
|
||||
fprintf(stderr, "RandomXMiner: destroyed VM after inner loop\n");
|
||||
} else {
|
||||
LogPrintf("RandomXMiner: WARNING myVM already null after inner loop, skipping destroy (would double-free)\n");
|
||||
fprintf(stderr, "RandomXMiner: WARNING myVM already null after inner loop, skipping destroy (would double-free)\n");
|
||||
}
|
||||
// Release shared lock so UpdateKey can acquire exclusive lock for dataset rebuild
|
||||
// VM is kept alive — its dataset pointer remains valid across rebuilds
|
||||
datasetLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user