Files
hush3/doc/CHANGELOG-randomx-optimization.md
dan_s 8a0eb77692 Fix RandomX validation exploit with difficulty reset, improve build system
- One-time difficulty reset to minimum for 17 blocks at activation height
- Separate RandomX build dirs for linux/win64 cross-compilation
- Add build target tracking to auto-clean on target switch
- Automated win64 release packaging to release-win64/
- Add build artifacts to .gitignore
- Miner memory diagnostics and large-page dataset fallback
2026-02-19 22:07:38 -06:00

2.5 KiB
Raw Permalink Blame History

Changelog: RandomX Mining Optimization

Summary

Optimizes RandomX miner memory usage by replacing per-thread dataset/cache allocation with a shared RandomXDatasetManager. Reduces memory footprint from ~2.3GB × N threads to ~2.3GB total.

Problem

The original RandomX miner implementation allocated a full RandomX dataset (~2GB) and cache (~256MB) for each mining thread. With multiple threads, this quickly exhausted available memory:

  • 4 threads: ~9.2GB
  • 8 threads: ~18.4GB
  • 16 threads: ~36.8GB

Solution

Implemented a shared RandomXDatasetManager that allocates a single dataset and cache, shared by all miner threads via read-only access (explicitly supported by RandomX design).

Changes

src/miner.cpp

  • Added RandomXDatasetManager class:

    • Manages a single shared RandomX cache and dataset.
    • Thread-safe key updates using boost::shared_mutex (readers-writer lock).
    • Initialize(key): Allocates cache and dataset, initializes with key, builds dataset using all CPU cores.
    • UpdateKey(newKey): Acquires exclusive lock, reinitializes cache with new key, rebuilds dataset.
    • GetDataset(): Returns pointer to shared dataset for VM creation.
    • AcquireSharedLock() / ReleaseSharedLock(): Miner threads hold shared lock while hashing to prevent key updates mid-hash.
    • Shutdown(): Releases all RandomX resources.
  • Modified GenerateBitcoins():

    • Initializes RandomXDatasetManager with initial key before spawning miner threads.
    • Calls Shutdown() when mining stops.
  • Modified RandomXMiner():

    • Creates lightweight per-thread VM using shared dataset (randomx_create_vm(..., manager.GetDataset())).
    • Acquires shared lock before hashing, releases after.
    • On key rotation: releases shared lock, calls manager.UpdateKey(), reacquires shared lock, recreates VM.
    • Cleanup only destroys thread's VM — dataset/cache owned by manager.

Memory Usage

Threads Before After
1 ~2.3GB ~2.3GB
4 ~9.2GB ~2.3GB
8 ~18.4GB ~2.3GB
16 ~36.8GB ~2.3GB

Thread Safety

  • RandomX dataset is read-only after initialization — safe to share across threads.
  • boost::shared_mutex ensures:
    • Multiple threads can hash concurrently (shared lock).
    • Key updates are exclusive (exclusive lock blocks until all shared locks release).
    • No thread hashes with stale dataset during key change.

Files Modified

File Lines Added Lines Removed
src/miner.cpp ~80 ~20