From 482a1f0b40289a5502cb5731aceaf3ca65aaa29f Mon Sep 17 00:00:00 2001 From: SChernykh <15806605+SChernykh@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:23:18 +0100 Subject: [PATCH] Linux: added support for transparent huge pages --- src/backend/cpu/CpuWorker.cpp | 4 ++-- src/crypto/common/MemoryPool.cpp | 2 +- src/crypto/common/VirtualMemory.cpp | 10 ++++++++++ src/crypto/common/VirtualMemory.h | 1 + src/crypto/common/VirtualMemory_unix.cpp | 10 ++++++++++ src/crypto/common/VirtualMemory_win.cpp | 6 ++++++ src/crypto/rx/RxDataset.cpp | 2 +- src/net/JobResults.cpp | 2 +- 8 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index bef2e898e..cba7e8839 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -87,14 +87,14 @@ xmrig::CpuWorker::CpuWorker(size_t id, const CpuLaunchData &data) : if (!cn_heavyZen3Memory) { // Round up number of threads to the multiple of 8 const size_t num_threads = ((m_threads + 7) / 8) * 8; - cn_heavyZen3Memory = new VirtualMemory(m_algorithm.l3() * num_threads, data.hugePages, false, false, node()); + cn_heavyZen3Memory = new VirtualMemory(m_algorithm.l3() * num_threads, data.hugePages, false, false, node(), VirtualMemory::kDefaultHugePageSize); } m_memory = cn_heavyZen3Memory; } else # endif { - m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, false, true, node()); + m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, false, true, node(), VirtualMemory::kDefaultHugePageSize); } # ifdef XMRIG_ALGO_GHOSTRIDER diff --git a/src/crypto/common/MemoryPool.cpp b/src/crypto/common/MemoryPool.cpp index e99757ee9..0e809125a 100644 --- a/src/crypto/common/MemoryPool.cpp +++ b/src/crypto/common/MemoryPool.cpp @@ -49,7 +49,7 @@ xmrig::MemoryPool::MemoryPool(size_t size, bool hugePages, uint32_t node) constexpr size_t alignment = 1 << 24; - m_memory = new VirtualMemory(size * pageSize + alignment, hugePages, false, false, node); + m_memory = new VirtualMemory(size * pageSize + alignment, hugePages, false, false, node, VirtualMemory::kDefaultHugePageSize); m_alignOffset = (alignment - (((size_t)m_memory->scratchpad()) % alignment)) % alignment; } diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp index e425750dd..d7d3a545e 100644 --- a/src/crypto/common/VirtualMemory.cpp +++ b/src/crypto/common/VirtualMemory.cpp @@ -75,6 +75,16 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages } m_scratchpad = static_cast(_mm_malloc(m_size, alignSize)); + + // Huge pages failed to allocate, but try to enable transparent huge pages for the range + if (alignSize >= kDefaultHugePageSize) { + if (m_scratchpad) { + adviseLargePages(m_scratchpad, m_size); + } + else { + m_scratchpad = static_cast(_mm_malloc(m_size, 64)); + } + } } diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index 3056cbaed..2edd3ae92 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -65,6 +65,7 @@ public: static void *allocateExecutableMemory(size_t size, bool hugePages); static void *allocateLargePagesMemory(size_t size); static void *allocateOneGbPagesMemory(size_t size); + static bool adviseLargePages(void *p, size_t size); static void destroy(); static void flushInstructionCache(void *p, size_t size); static void freeLargePagesMemory(void *p, size_t size); diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index fa9a3ccb2..471c9cf07 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -276,6 +276,16 @@ bool xmrig::VirtualMemory::allocateOneGbPagesMemory() } +bool xmrig::VirtualMemory::adviseLargePages(void *p, size_t size) +{ +# ifdef XMRIG_OS_LINUX + return (madvise(p, size, MADV_HUGEPAGE) == 0); +# else + return false; +# endif +} + + void xmrig::VirtualMemory::freeLargePagesMemory() { if (m_flags.test(FLAG_LOCK)) { diff --git a/src/crypto/common/VirtualMemory_win.cpp b/src/crypto/common/VirtualMemory_win.cpp index acf8119fa..28f515bac 100644 --- a/src/crypto/common/VirtualMemory_win.cpp +++ b/src/crypto/common/VirtualMemory_win.cpp @@ -260,6 +260,12 @@ bool xmrig::VirtualMemory::allocateOneGbPagesMemory() } +bool xmrig::VirtualMemory::adviseLargePages(void *p, size_t size) +{ + return false; +} + + void xmrig::VirtualMemory::freeLargePagesMemory() { freeLargePagesMemory(m_scratchpad, m_size); diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index 9c41dd43f..3495d7baa 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -215,7 +215,7 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages) return; } - m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node); + m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node, VirtualMemory::kDefaultHugePageSize); if (m_memory->isOneGbPages()) { m_scratchpadOffset = maxSize() + RANDOMX_CACHE_MAX_SIZE; diff --git a/src/net/JobResults.cpp b/src/net/JobResults.cpp index 19a1dc43c..57e4a8db0 100644 --- a/src/net/JobResults.cpp +++ b/src/net/JobResults.cpp @@ -115,7 +115,7 @@ static inline void checkHash(const JobBundle &bundle, std::vector &re static void getResults(JobBundle &bundle, std::vector &results, uint32_t &errors, bool hwAES) { const auto &algorithm = bundle.job.algorithm(); - auto memory = new VirtualMemory(algorithm.l3(), false, false, false); + auto memory = new VirtualMemory(algorithm.l3(), false, false, false, 0, VirtualMemory::kDefaultHugePageSize); alignas(16) uint8_t hash[32]{ 0 }; if (algorithm.family() == Algorithm::RANDOM_X) {