From d32df84ca5189a98050a6a190f092e33600acbe6 Mon Sep 17 00:00:00 2001 From: XMRig Date: Sun, 8 Dec 2019 23:17:39 +0700 Subject: [PATCH] Memory allocation refactoring. --- CMakeLists.txt | 7 ++ src/backend/common/interfaces/IRxStorage.h | 3 +- src/backend/cpu/CpuBackend.cpp | 40 ++++---- src/backend/cpu/CpuWorker.cpp | 2 +- src/crypto/common/HugePagesInfo.cpp | 50 ++++++++++ src/crypto/common/HugePagesInfo.h | 67 ++++++++++++++ src/crypto/common/LinuxMemory.cpp | 103 +++++++++++++++++++++ src/crypto/common/LinuxMemory.h | 49 ++++++++++ src/crypto/common/MemoryPool.cpp | 2 +- src/crypto/common/VirtualMemory.cpp | 17 +++- src/crypto/common/VirtualMemory.h | 11 ++- src/crypto/common/VirtualMemory_unix.cpp | 17 +++- src/crypto/randomx/allocator.cpp | 10 +- src/crypto/randomx/common.hpp | 2 - src/crypto/randomx/dataset.hpp | 2 - src/crypto/randomx/randomx.cpp | 69 +++----------- src/crypto/randomx/randomx.h | 4 +- src/crypto/randomx/virtual_memory.cpp | 10 -- src/crypto/randomx/virtual_memory.hpp | 1 - src/crypto/rx/Rx.cpp | 8 +- src/crypto/rx/Rx.h | 5 +- src/crypto/rx/RxBasicStorage.cpp | 35 ++++--- src/crypto/rx/RxBasicStorage.h | 2 +- src/crypto/rx/RxCache.cpp | 50 +++++----- src/crypto/rx/RxCache.h | 16 ++-- src/crypto/rx/RxDataset.cpp | 90 +++++++++--------- src/crypto/rx/RxDataset.h | 13 ++- src/crypto/rx/RxNUMAStorage.cpp | 92 ++++++++++-------- src/crypto/rx/RxNUMAStorage.h | 2 +- src/crypto/rx/RxQueue.cpp | 4 +- src/crypto/rx/RxQueue.h | 3 +- src/net/JobResults.cpp | 2 +- 32 files changed, 516 insertions(+), 272 deletions(-) create mode 100644 src/crypto/common/HugePagesInfo.cpp create mode 100644 src/crypto/common/HugePagesInfo.h create mode 100644 src/crypto/common/LinuxMemory.cpp create mode 100644 src/crypto/common/LinuxMemory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e507a03c6..b65d53379 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ set(HEADERS_CRYPTO src/crypto/cn/soft_aes.h src/crypto/common/Algorithm.h src/crypto/common/Coin.h + src/crypto/common/HugePagesInfo.h src/crypto/common/keccak.h src/crypto/common/MemoryPool.h src/crypto/common/Nonce.h @@ -115,6 +116,7 @@ set(SOURCES_CRYPTO src/crypto/cn/CnHash.cpp src/crypto/common/Algorithm.cpp src/crypto/common/Coin.cpp + src/crypto/common/HugePagesInfo.cpp src/crypto/common/keccak.cpp src/crypto/common/MemoryPool.cpp src/crypto/common/Nonce.cpp @@ -154,6 +156,11 @@ else() if (XMRIG_OS_ANDROID) set(EXTRA_LIBS pthread rt dl log) elseif (XMRIG_OS_LINUX) + list(APPEND SOURCES_OS + src/crypto/common/LinuxMemory.h + src/crypto/common/LinuxMemory.cpp + ) + set(EXTRA_LIBS pthread rt dl) elseif (XMRIG_OS_FREEBSD) set(EXTRA_LIBS kvm pthread) diff --git a/src/backend/common/interfaces/IRxStorage.h b/src/backend/common/interfaces/IRxStorage.h index 372eee6f9..567885185 100644 --- a/src/backend/common/interfaces/IRxStorage.h +++ b/src/backend/common/interfaces/IRxStorage.h @@ -25,6 +25,7 @@ #include "crypto/rx/RxConfig.h" +#include "crypto/common/HugePagesInfo.h" #include @@ -44,8 +45,8 @@ class IRxStorage public: virtual ~IRxStorage() = default; + virtual HugePagesInfo hugePages() const = 0; virtual RxDataset *dataset(const Job &job, uint32_t nodeId) const = 0; - virtual std::pair hugePages() const = 0; virtual void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) = 0; }; diff --git a/src/backend/cpu/CpuBackend.cpp b/src/backend/cpu/CpuBackend.cpp index ddee67683..ac4594975 100644 --- a/src/backend/cpu/CpuBackend.cpp +++ b/src/backend/cpu/CpuBackend.cpp @@ -68,17 +68,15 @@ static std::mutex mutex; struct CpuLaunchStatus { public: - inline size_t hugePages() const { return m_hugePages; } - inline size_t memory() const { return m_ways * m_memory; } - inline size_t pages() const { return m_pages; } - inline size_t threads() const { return m_threads; } - inline size_t ways() const { return m_ways; } + inline const HugePagesInfo &hugePages() const { return m_hugePages; } + inline size_t memory() const { return m_ways * m_memory; } + inline size_t threads() const { return m_threads; } + inline size_t ways() const { return m_ways; } inline void start(const std::vector &threads, size_t memory) { - m_hugePages = 0; + m_hugePages.reset(); m_memory = memory; - m_pages = 0; m_started = 0; m_errors = 0; m_threads = threads.size(); @@ -89,11 +87,9 @@ public: inline bool started(IWorker *worker, bool ready) { if (ready) { - auto hugePages = worker->memory()->hugePages(); - m_started++; - m_hugePages += hugePages.first; - m_pages += hugePages.second; + + m_hugePages += worker->memory()->hugePages(); m_ways += worker->intensity(); } else { @@ -115,19 +111,18 @@ public: tag, m_errors == 0 ? CYAN_BOLD_S : YELLOW_BOLD_S, m_started, m_threads, m_ways, - (m_hugePages == m_pages ? GREEN_BOLD_S : (m_hugePages == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), - m_hugePages == 0 ? 0.0 : static_cast(m_hugePages) / m_pages * 100.0, - m_hugePages, m_pages, + (m_hugePages.isFullyAllocated() ? GREEN_BOLD_S : (m_hugePages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + m_hugePages.percent(), + m_hugePages.allocated, m_hugePages.total, memory() / 1024, Chrono::steadyMSecs() - m_ts ); } private: + HugePagesInfo m_hugePages; size_t m_errors = 0; - size_t m_hugePages = 0; size_t m_memory = 0; - size_t m_pages = 0; size_t m_started = 0; size_t m_threads = 0; size_t m_ways = 0; @@ -169,18 +164,17 @@ public: rapidjson::Value hugePages(int version, rapidjson::Document &doc) { - std::pair pages(0, 0); + HugePagesInfo pages; # ifdef XMRIG_ALGO_RANDOMX if (algo.family() == Algorithm::RANDOM_X) { - pages = Rx::hugePages(); + pages += Rx::hugePages(); } # endif mutex.lock(); - pages.first += status.hugePages(); - pages.second += status.pages(); + pages += status.hugePages(); mutex.unlock(); @@ -188,11 +182,11 @@ public: if (version > 1) { hugepages.SetArray(); - hugepages.PushBack(pages.first, doc.GetAllocator()); - hugepages.PushBack(pages.second, doc.GetAllocator()); + hugepages.PushBack(static_cast(pages.allocated), doc.GetAllocator()); + hugepages.PushBack(static_cast(pages.total), doc.GetAllocator()); } else { - hugepages = pages.first == pages.second; + hugepages = pages.isFullyAllocated(); } return hugepages; diff --git a/src/backend/cpu/CpuWorker.cpp b/src/backend/cpu/CpuWorker.cpp index 5d58106d8..f93f7dacf 100644 --- a/src/backend/cpu/CpuWorker.cpp +++ b/src/backend/cpu/CpuWorker.cpp @@ -63,7 +63,7 @@ xmrig::CpuWorker::CpuWorker(size_t id, const CpuLaunchData &data) : m_miner(data.miner), m_ctx() { - m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, true, m_node); + m_memory = new VirtualMemory(m_algorithm.l3() * N, data.hugePages, false, true, m_node); } diff --git a/src/crypto/common/HugePagesInfo.cpp b/src/crypto/common/HugePagesInfo.cpp new file mode 100644 index 000000000..3108c7de6 --- /dev/null +++ b/src/crypto/common/HugePagesInfo.cpp @@ -0,0 +1,50 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/common/HugePagesInfo.h" +#include "crypto/common/VirtualMemory.h" + + +namespace xmrig { + +constexpr size_t twoMiB = 2U * 1024U * 1024U; +constexpr size_t oneGiB = 1024U * 1024U * 1024U; + +} // namespace xmrig + + +xmrig::HugePagesInfo::HugePagesInfo(const VirtualMemory *memory) +{ + if (memory->isOneGbPages()) { + size = VirtualMemory::align(memory->size(), oneGiB); + total = size / oneGiB; + allocated = size / oneGiB; + } + else { + size = memory->size(); + total = size / twoMiB; + allocated = memory->isHugePages() ? total : 0; + } +} diff --git a/src/crypto/common/HugePagesInfo.h b/src/crypto/common/HugePagesInfo.h new file mode 100644 index 000000000..1dc93bb4f --- /dev/null +++ b/src/crypto/common/HugePagesInfo.h @@ -0,0 +1,67 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_HUGEPAGESINFO_H +#define XMRIG_HUGEPAGESINFO_H + + +#include +#include + + +namespace xmrig { + + +class VirtualMemory; + + +class HugePagesInfo +{ +public: + HugePagesInfo() = default; + HugePagesInfo(const VirtualMemory *memory); + + size_t allocated = 0; + size_t total = 0; + size_t size = 0; + + inline bool isFullyAllocated() const { return allocated == total; } + inline double percent() const { return allocated == 0 ? 0.0 : static_cast(allocated) / total * 100.0; } + inline void reset() { allocated = 0; total = 0; size = 0; } + + inline HugePagesInfo &operator+=(const HugePagesInfo &other) + { + allocated += other.allocated; + total += other.total; + size += other.size; + + return *this; + } +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_HUGEPAGESINFO_H */ diff --git a/src/crypto/common/LinuxMemory.cpp b/src/crypto/common/LinuxMemory.cpp new file mode 100644 index 000000000..b7c2000f9 --- /dev/null +++ b/src/crypto/common/LinuxMemory.cpp @@ -0,0 +1,103 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +//#include + +#include "crypto/common/LinuxMemory.h" +#include "base/io/log/Log.h" +#include "crypto/common/VirtualMemory.h" +#include "backend/cpu/Cpu.h" + + +#include +#include +#include +#include + + +namespace xmrig { + + +static std::mutex mutex; +constexpr size_t twoMiB = 2U * 1024U * 1024U; +constexpr size_t oneGiB = 1024U * 1024U * 1024U; + + +static inline std::string sysfs_path(uint32_t node, bool oneGbPages, bool nr) +{ + return "/sys/devices/system/node/node" + std::to_string(node) + "/hugepages/hugepages-" + (oneGbPages ? "1048576" : "2048") + "kB/" + (nr ? "nr" : "free") + "_hugepages"; +} + + +static inline bool write_nr_hugepages(uint32_t node, bool oneGbPages, uint64_t count) { return LinuxMemory::write(sysfs_path(node, oneGbPages, true).c_str(), count); } +static inline int64_t free_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, false).c_str()); } +static inline int64_t nr_hugepages(uint32_t node, bool oneGbPages) { return LinuxMemory::read(sysfs_path(node, oneGbPages, true).c_str()); } + + +} // namespace xmrig + + +bool xmrig::LinuxMemory::reserve(size_t size, uint32_t node, bool oneGbPages) +{ + std::lock_guard lock(mutex); + + const size_t pageSize = oneGbPages ? oneGiB : twoMiB; + const size_t required = VirtualMemory::align(size, pageSize) / pageSize; + + const auto available = free_hugepages(node, oneGbPages); + if (available < 0 || static_cast(available) >= required) { + return false; + } + + return write_nr_hugepages(node, oneGbPages, std::max(nr_hugepages(node, oneGbPages), 0) + (required - available)); +} + + +bool xmrig::LinuxMemory::write(const char *path, uint64_t value) +{ + std::ofstream file(path, std::ios::out | std::ios::binary | std::ios::trunc); + if (!file.is_open()) { + return false; + } + + file << value; + file.flush(); + + return true; +} + + +int64_t xmrig::LinuxMemory::read(const char *path) +{ + std::ifstream file(path); + if (!file.is_open()) { + return -1; + } + + uint64_t value = 0; + file >> value; + + return value; +} diff --git a/src/crypto/common/LinuxMemory.h b/src/crypto/common/LinuxMemory.h new file mode 100644 index 000000000..aa46a6fcd --- /dev/null +++ b/src/crypto/common/LinuxMemory.h @@ -0,0 +1,49 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_LINUXMEMORY_H +#define XMRIG_LINUXMEMORY_H + + +#include +#include + + +namespace xmrig { + + +class LinuxMemory +{ +public: + static bool reserve(size_t size, uint32_t node, bool oneGbPages = false); + + static bool write(const char *path, uint64_t value); + static int64_t read(const char *path); +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_LINUXMEMORY_H */ diff --git a/src/crypto/common/MemoryPool.cpp b/src/crypto/common/MemoryPool.cpp index 2b2da6591..6e17d752b 100644 --- a/src/crypto/common/MemoryPool.cpp +++ b/src/crypto/common/MemoryPool.cpp @@ -47,7 +47,7 @@ xmrig::MemoryPool::MemoryPool(size_t size, bool hugePages, uint32_t node) return; } - m_memory = new VirtualMemory(size * pageSize, hugePages, false, node); + m_memory = new VirtualMemory(size * pageSize, hugePages, false, false, node); } diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp index 0eaef3c5e..14909f1b7 100644 --- a/src/crypto/common/VirtualMemory.cpp +++ b/src/crypto/common/VirtualMemory.cpp @@ -46,10 +46,13 @@ namespace xmrig { static IMemoryPool *pool = nullptr; static std::mutex mutex; +constexpr size_t twoMiB = 2U * 1024U * 1024U; +constexpr size_t oneGiB = 1024U * 1024U * 1024U; + } // namespace xmrig -xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool usePool, uint32_t node, size_t alignSize) : +xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node, size_t alignSize) : m_size(align(size)), m_node(node) { @@ -68,6 +71,10 @@ xmrig::VirtualMemory::VirtualMemory(size_t size, bool hugePages, bool usePool, u } } + if (oneGbPages && allocateOneGbPagesMemory()) { + return; + } + if (hugePages && allocateLargePagesMemory()) { return; } @@ -86,7 +93,7 @@ xmrig::VirtualMemory::~VirtualMemory() std::lock_guard lock(mutex); pool->release(m_node); } - else if (isHugePages()) { + else if (isHugePages() || isOneGbPages()) { freeLargePagesMemory(); } else { @@ -95,6 +102,12 @@ xmrig::VirtualMemory::~VirtualMemory() } +xmrig::HugePagesInfo xmrig::VirtualMemory::hugePages() const +{ + return { this }; +} + + #ifndef XMRIG_FEATURE_HWLOC uint32_t xmrig::VirtualMemory::bindToNUMANode(int64_t) { diff --git a/src/crypto/common/VirtualMemory.h b/src/crypto/common/VirtualMemory.h index e5101f525..f27e5908f 100644 --- a/src/crypto/common/VirtualMemory.h +++ b/src/crypto/common/VirtualMemory.h @@ -29,6 +29,7 @@ #include "base/tools/Object.h" +#include "crypto/common/HugePagesInfo.h" #include @@ -45,17 +46,16 @@ class VirtualMemory public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(VirtualMemory) - VirtualMemory(size_t size, bool hugePages, bool usePool, uint32_t node = 0, size_t alignSize = 64); + VirtualMemory(size_t size, bool hugePages, bool oneGbPages, bool usePool, uint32_t node = 0, size_t alignSize = 64); ~VirtualMemory(); inline bool isHugePages() const { return m_flags.test(FLAG_HUGEPAGES); } + inline bool isOneGbPages() const { return m_flags.test(FLAG_1GB_PAGES); } inline size_t size() const { return m_size; } + inline uint8_t *raw() const { return m_scratchpad; } inline uint8_t *scratchpad() const { return m_scratchpad; } - inline std::pair hugePages() const - { - return { isHugePages() ? (align(size()) / 2097152) : 0, align(size()) / 2097152 }; - } + HugePagesInfo hugePages() const; static bool isHugepagesAvailable(); static bool isOneGbPagesAvailable(); @@ -75,6 +75,7 @@ public: private: enum Flags { FLAG_HUGEPAGES, + FLAG_1GB_PAGES, FLAG_LOCK, FLAG_EXTERNAL, FLAG_MAX diff --git a/src/crypto/common/VirtualMemory_unix.cpp b/src/crypto/common/VirtualMemory_unix.cpp index 391351714..0c77ba091 100644 --- a/src/crypto/common/VirtualMemory_unix.cpp +++ b/src/crypto/common/VirtualMemory_unix.cpp @@ -39,8 +39,11 @@ #endif -#if defined (XMRIG_OS_LINUX) && (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT)) -# define XMRIG_HAS_1GB_PAGES +#if defined(XMRIG_OS_LINUX) +# if (defined(MAP_HUGE_1GB) || defined(MAP_HUGE_SHIFT)) +# define XMRIG_HAS_1GB_PAGES +# endif +# include "crypto/common/LinuxMemory.h" #endif @@ -141,6 +144,10 @@ void xmrig::VirtualMemory::osInit(bool) bool xmrig::VirtualMemory::allocateLargePagesMemory() { +# if defined(XMRIG_OS_LINUX) + LinuxMemory::reserve(m_size, m_node); +# endif + m_scratchpad = static_cast(allocateLargePagesMemory(m_size)); if (m_scratchpad) { m_flags.set(FLAG_HUGEPAGES, true); @@ -160,9 +167,13 @@ bool xmrig::VirtualMemory::allocateLargePagesMemory() bool xmrig::VirtualMemory::allocateOneGbPagesMemory() { +# if defined(XMRIG_HAS_1GB_PAGES) + LinuxMemory::reserve(m_size, m_node, true); +# endif + m_scratchpad = static_cast(allocateOneGbPagesMemory(m_size)); if (m_scratchpad) { - m_flags.set(FLAG_HUGEPAGES, true); + m_flags.set(FLAG_1GB_PAGES, true); madvise(m_scratchpad, m_size, MADV_RANDOM | MADV_WILLNEED); diff --git a/src/crypto/randomx/allocator.cpp b/src/crypto/randomx/allocator.cpp index d46393f1f..770e60f9f 100644 --- a/src/crypto/randomx/allocator.cpp +++ b/src/crypto/randomx/allocator.cpp @@ -43,7 +43,7 @@ namespace randomx { } template - void AlignedAllocator::freeMemory(void* ptr, size_t count) { + void AlignedAllocator::freeMemory(void* ptr, size_t) { rx_aligned_free(ptr); } @@ -57,12 +57,4 @@ namespace randomx { freePagedMemory(ptr, count); }; - void* OneGbPageAllocator::allocMemory(size_t count) { - return allocOneGbPagesMemory(count); - } - - void OneGbPageAllocator::freeMemory(void* ptr, size_t count) { - freePagedMemory(ptr, count); - }; - } diff --git a/src/crypto/randomx/common.hpp b/src/crypto/randomx/common.hpp index 48f31bac2..cea5f5be6 100644 --- a/src/crypto/randomx/common.hpp +++ b/src/crypto/randomx/common.hpp @@ -167,7 +167,5 @@ namespace randomx { typedef void(ProgramFunc)(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t); typedef void(DatasetInitFunc)(randomx_cache* cache, uint8_t* dataset, uint32_t startBlock, uint32_t endBlock); - typedef void(DatasetDeallocFunc)(randomx_dataset*); - typedef void(CacheDeallocFunc)(randomx_cache*); typedef void(CacheInitializeFunc)(randomx_cache*, const void*, size_t); } diff --git a/src/crypto/randomx/dataset.hpp b/src/crypto/randomx/dataset.hpp index 6c179b5d1..a40cf1d76 100644 --- a/src/crypto/randomx/dataset.hpp +++ b/src/crypto/randomx/dataset.hpp @@ -38,13 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* Global scope for C binding */ struct randomx_dataset { uint8_t* memory = nullptr; - randomx::DatasetDeallocFunc* dealloc; }; /* Global scope for C binding */ struct randomx_cache { uint8_t* memory = nullptr; - randomx::CacheDeallocFunc* dealloc; randomx::JitCompiler* jit; randomx::CacheInitializeFunc* initialize; randomx::DatasetInitFunc* datasetInit; diff --git a/src/crypto/randomx/randomx.cpp b/src/crypto/randomx/randomx.cpp index 08f4f241b..8b1cfe2ce 100644 --- a/src/crypto/randomx/randomx.cpp +++ b/src/crypto/randomx/randomx.cpp @@ -272,42 +272,24 @@ RandomX_ConfigurationBase RandomX_CurrentConfig; extern "C" { - randomx_cache *randomx_alloc_cache(randomx_flags flags) { + randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory) { randomx_cache *cache = nullptr; try { cache = new randomx_cache(); - switch (flags & (RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES)) { + switch (flags & RANDOMX_FLAG_JIT) { case RANDOMX_FLAG_DEFAULT: - cache->dealloc = &randomx::deallocCache; - cache->jit = nullptr; - cache->initialize = &randomx::initCache; - cache->datasetInit = &randomx::initDataset; - cache->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE); + cache->jit = nullptr; + cache->initialize = &randomx::initCache; + cache->datasetInit = &randomx::initDataset; + cache->memory = memory; break; case RANDOMX_FLAG_JIT: - cache->dealloc = &randomx::deallocCache; - cache->jit = new randomx::JitCompiler(); - cache->initialize = &randomx::initCacheCompile; - cache->datasetInit = cache->jit->getDatasetInitFunc(); - cache->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE); - break; - - case RANDOMX_FLAG_LARGE_PAGES: - cache->dealloc = &randomx::deallocCache; - cache->jit = nullptr; - cache->initialize = &randomx::initCache; - cache->datasetInit = &randomx::initDataset; - cache->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE); - break; - - case RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES: - cache->dealloc = &randomx::deallocCache; - cache->jit = new randomx::JitCompiler(); - cache->initialize = &randomx::initCacheCompile; - cache->datasetInit = cache->jit->getDatasetInitFunc(); - cache->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_CACHE_MAX_SIZE); + cache->jit = new randomx::JitCompiler(); + cache->initialize = &randomx::initCacheCompile; + cache->datasetInit = cache->jit->getDatasetInitFunc(); + cache->memory = memory; break; default: @@ -331,35 +313,12 @@ extern "C" { } void randomx_release_cache(randomx_cache* cache) { - assert(cache != nullptr); - cache->dealloc(cache); delete cache; } - randomx_dataset *randomx_alloc_dataset(randomx_flags flags) { - randomx_dataset *dataset = nullptr; - - try { - dataset = new randomx_dataset(); - if (flags & RANDOMX_FLAG_1GB_PAGES) { - dataset->dealloc = &randomx::deallocDataset; - dataset->memory = (uint8_t*)randomx::OneGbPageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); - } - else if (flags & RANDOMX_FLAG_LARGE_PAGES) { - dataset->dealloc = &randomx::deallocDataset; - dataset->memory = (uint8_t*)randomx::LargePageAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); - } - else { - dataset->dealloc = &randomx::deallocDataset; - dataset->memory = (uint8_t*)randomx::DefaultAllocator::allocMemory(RANDOMX_DATASET_MAX_SIZE); - } - } - catch (std::exception &ex) { - if (dataset != nullptr) { - randomx_release_dataset(dataset); - dataset = nullptr; - } - } + randomx_dataset *randomx_create_dataset(uint8_t *memory) { + auto dataset = new randomx_dataset(); + dataset->memory = memory; return dataset; } @@ -384,8 +343,6 @@ extern "C" { } void randomx_release_dataset(randomx_dataset *dataset) { - assert(dataset != nullptr); - dataset->dealloc(dataset); delete dataset; } diff --git a/src/crypto/randomx/randomx.h b/src/crypto/randomx/randomx.h index 84ae7dfc8..923142299 100644 --- a/src/crypto/randomx/randomx.h +++ b/src/crypto/randomx/randomx.h @@ -215,7 +215,7 @@ extern "C" { * NULL is returned if memory allocation fails or if the RANDOMX_FLAG_JIT * is set and JIT compilation is not supported on the current platform. */ -RANDOMX_EXPORT randomx_cache *randomx_alloc_cache(randomx_flags flags); +RANDOMX_EXPORT randomx_cache *randomx_create_cache(randomx_flags flags, uint8_t *memory); /** * Initializes the cache memory and SuperscalarHash using the provided key value. @@ -242,7 +242,7 @@ RANDOMX_EXPORT void randomx_release_cache(randomx_cache* cache); * @return Pointer to an allocated randomx_dataset structure. * NULL is returned if memory allocation fails. */ -RANDOMX_EXPORT randomx_dataset *randomx_alloc_dataset(randomx_flags flags); +RANDOMX_EXPORT randomx_dataset *randomx_create_dataset(uint8_t *memory); /** * Gets the number of items contained in the dataset. diff --git a/src/crypto/randomx/virtual_memory.cpp b/src/crypto/randomx/virtual_memory.cpp index 48a8a8d25..06165ffb6 100644 --- a/src/crypto/randomx/virtual_memory.cpp +++ b/src/crypto/randomx/virtual_memory.cpp @@ -53,16 +53,6 @@ void* allocLargePagesMemory(std::size_t bytes) { } -void* allocOneGbPagesMemory(std::size_t bytes) { - void* mem = xmrig::VirtualMemory::allocateOneGbPagesMemory(bytes); - if (mem == nullptr) { - throw std::runtime_error("Failed to allocate 1GB pages memory"); - } - - return mem; -} - - void freePagedMemory(void* ptr, std::size_t bytes) { xmrig::VirtualMemory::freeLargePagesMemory(ptr, bytes); } diff --git a/src/crypto/randomx/virtual_memory.hpp b/src/crypto/randomx/virtual_memory.hpp index 8c5b49005..d3b31db12 100644 --- a/src/crypto/randomx/virtual_memory.hpp +++ b/src/crypto/randomx/virtual_memory.hpp @@ -32,5 +32,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. void* allocExecutableMemory(std::size_t); void* allocLargePagesMemory(std::size_t); -void* allocOneGbPagesMemory(std::size_t); void freePagedMemory(void*, std::size_t); diff --git a/src/crypto/rx/Rx.cpp b/src/crypto/rx/Rx.cpp index 84c9b5fc9..369b0aacf 100644 --- a/src/crypto/rx/Rx.cpp +++ b/src/crypto/rx/Rx.cpp @@ -83,15 +83,15 @@ bool xmrig::Rx::isReady(const Job &job) } -xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) +xmrig::HugePagesInfo xmrig::Rx::hugePages() { - return d_ptr->queue.dataset(job, nodeId); + return d_ptr->queue.hugePages(); } -std::pair xmrig::Rx::hugePages() +xmrig::RxDataset *xmrig::Rx::dataset(const Job &job, uint32_t nodeId) { - return d_ptr->queue.hugePages(); + return d_ptr->queue.dataset(job, nodeId); } diff --git a/src/crypto/rx/Rx.h b/src/crypto/rx/Rx.h index abaca9200..d26304451 100644 --- a/src/crypto/rx/Rx.h +++ b/src/crypto/rx/Rx.h @@ -32,6 +32,9 @@ #include +#include "crypto/common/HugePagesInfo.h" + + namespace xmrig { @@ -49,8 +52,8 @@ class Rx public: static bool init(const Job &job, const RxConfig &config, const CpuConfig &cpu); static bool isReady(const Job &job); + static HugePagesInfo hugePages(); static RxDataset *dataset(const Job &job, uint32_t nodeId); - static std::pair hugePages(); static void destroy(); static void init(IRxListener *listener); }; diff --git a/src/crypto/rx/RxBasicStorage.cpp b/src/crypto/rx/RxBasicStorage.cpp index a0656e46b..079bf95c9 100644 --- a/src/crypto/rx/RxBasicStorage.cpp +++ b/src/crypto/rx/RxBasicStorage.cpp @@ -73,7 +73,7 @@ public: { const uint64_t ts = Chrono::steadyMSecs(); - m_dataset = new RxDataset(hugePages, oneGbPages, true, mode); + m_dataset = new RxDataset(hugePages, oneGbPages, true, mode, 0); printAllocStatus(ts); } @@ -94,18 +94,17 @@ private: void printAllocStatus(uint64_t ts) { if (m_dataset->get() != nullptr) { - const auto pages = m_dataset->hugePages(); - const double percent = pages.first == 0 ? 0.0 : static_cast(pages.first) / pages.second * 100.0; + const auto pages = m_dataset->hugePages(); LOG_INFO("%s" GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") BLACK_BOLD(" (%zu+%zu)") " huge pages %s%1.0f%% %u/%u" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), - m_dataset->size() / oneMiB, + pages.size / oneMiB, RxDataset::maxSize() / oneMiB, RxCache::maxSize() / oneMiB, - (pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), - percent, - pages.first, - pages.second, + (pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + pages.percent(), + pages.allocated, + pages.total, m_dataset->cache()->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", Chrono::steadyMSecs() - ts ); @@ -137,6 +136,16 @@ xmrig::RxBasicStorage::~RxBasicStorage() } +xmrig::HugePagesInfo xmrig::RxBasicStorage::hugePages() const +{ + if (!d_ptr->dataset()) { + return {}; + } + + return d_ptr->dataset()->hugePages(); +} + + xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const { if (!d_ptr->isReady(job)) { @@ -147,16 +156,6 @@ xmrig::RxDataset *xmrig::RxBasicStorage::dataset(const Job &job, uint32_t) const } -std::pair xmrig::RxBasicStorage::hugePages() const -{ - if (!d_ptr->dataset()) { - return { 0U, 0U }; - } - - return d_ptr->dataset()->hugePages(); -} - - void xmrig::RxBasicStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) { d_ptr->setSeed(seed); diff --git a/src/crypto/rx/RxBasicStorage.h b/src/crypto/rx/RxBasicStorage.h index bd8a5e00d..1f50af576 100644 --- a/src/crypto/rx/RxBasicStorage.h +++ b/src/crypto/rx/RxBasicStorage.h @@ -48,8 +48,8 @@ public: ~RxBasicStorage() override; protected: + HugePagesInfo hugePages() const override; RxDataset *dataset(const Job &job, uint32_t nodeId) const override; - std::pair hugePages() const override; void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override; private: diff --git a/src/crypto/rx/RxCache.cpp b/src/crypto/rx/RxCache.cpp index a248ea5cc..f58f30247 100644 --- a/src/crypto/rx/RxCache.cpp +++ b/src/crypto/rx/RxCache.cpp @@ -35,30 +35,25 @@ static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mism -xmrig::RxCache::RxCache(bool hugePages) +xmrig::RxCache::RxCache(bool hugePages, uint32_t nodeId) { - if (hugePages) { - m_flags = RANDOMX_FLAG_JIT | RANDOMX_FLAG_LARGE_PAGES; - m_cache = randomx_alloc_cache(static_cast(m_flags)); - } + m_memory = new VirtualMemory(maxSize(), hugePages, false, false, nodeId); - if (!m_cache) { - m_flags = RANDOMX_FLAG_JIT; - m_cache = randomx_alloc_cache(static_cast(m_flags)); - } + create(m_memory->raw()); +} - if (!m_cache) { - m_flags = RANDOMX_FLAG_DEFAULT; - m_cache = randomx_alloc_cache(static_cast(m_flags)); - } + +xmrig::RxCache::RxCache(uint8_t *memory) +{ + create(memory); } xmrig::RxCache::~RxCache() { - if (m_cache) { - randomx_release_cache(m_cache); - } + randomx_release_cache(m_cache); + + delete m_memory; } @@ -75,15 +70,18 @@ bool xmrig::RxCache::init(const Buffer &seed) } -std::pair xmrig::RxCache::hugePages() const +xmrig::HugePagesInfo xmrig::RxCache::hugePages() const { - constexpr size_t twoMiB = 2u * 1024u * 1024u; - constexpr size_t total = VirtualMemory::align(maxSize(), twoMiB) / twoMiB; - - uint32_t count = 0; - if (isHugePages()) { - count += total; - } - - return { count, total }; + return m_memory ? m_memory->hugePages() : HugePagesInfo(); +} + + +void xmrig::RxCache::create(uint8_t *memory) +{ + m_cache = randomx_create_cache(RANDOMX_FLAG_JIT, memory); + + if (!m_cache) { + m_jit = false; + m_cache = randomx_create_cache(RANDOMX_FLAG_DEFAULT, memory); + } } diff --git a/src/crypto/rx/RxCache.h b/src/crypto/rx/RxCache.h index 84635292b..d1822b30a 100644 --- a/src/crypto/rx/RxCache.h +++ b/src/crypto/rx/RxCache.h @@ -33,6 +33,7 @@ #include "base/tools/Buffer.h" #include "base/tools/Object.h" +#include "crypto/common/HugePagesInfo.h" #include "crypto/randomx/configuration.h" @@ -48,24 +49,27 @@ class RxCache public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxCache) - RxCache(bool hugePages = true); + RxCache(bool hugePages, uint32_t nodeId); + RxCache(uint8_t *memory); ~RxCache(); - inline bool isHugePages() const { return m_flags & 1; } - inline bool isJIT() const { return m_flags & 8; } + inline bool isJIT() const { return m_jit; } inline const Buffer &seed() const { return m_seed; } inline randomx_cache *get() const { return m_cache; } inline size_t size() const { return maxSize(); } bool init(const Buffer &seed); - std::pair hugePages() const; + HugePagesInfo hugePages() const; static inline constexpr size_t maxSize() { return RANDOMX_CACHE_MAX_SIZE; } private: + void create(uint8_t *memory); + + bool m_jit = true; Buffer m_seed; - int m_flags = 0; - randomx_cache *m_cache = nullptr; + randomx_cache *m_cache = nullptr; + VirtualMemory *m_memory = nullptr; }; diff --git a/src/crypto/rx/RxDataset.cpp b/src/crypto/rx/RxDataset.cpp index 5786926a3..b2f934eb0 100644 --- a/src/crypto/rx/RxDataset.cpp +++ b/src/crypto/rx/RxDataset.cpp @@ -38,9 +38,6 @@ #include -static_assert(RANDOMX_FLAG_LARGE_PAGES == 1, "RANDOMX_FLAG_LARGE_PAGES flag mismatch"); - - namespace xmrig { @@ -55,18 +52,26 @@ static void init_dataset_wrapper(randomx_dataset *dataset, randomx_cache *cache, } // namespace xmrig -xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode) : - m_mode(mode) +xmrig::RxDataset::RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode, uint32_t node) : + m_mode(mode), + m_node(node) { allocate(hugePages, oneGbPages); + if (isOneGbPages()) { + m_cache = new RxCache(m_memory->raw() + VirtualMemory::align(maxSize())); + + return; + } + if (cache) { - m_cache = new RxCache(hugePages); + m_cache = new RxCache(hugePages, node); } } xmrig::RxDataset::RxDataset(RxCache *cache) : + m_node(0), m_cache(cache) { } @@ -74,11 +79,10 @@ xmrig::RxDataset::RxDataset(RxCache *cache) : xmrig::RxDataset::~RxDataset() { - if (m_dataset) { - randomx_release_dataset(m_dataset); - } + randomx_release_dataset(m_dataset); delete m_cache; + delete m_memory; } @@ -118,6 +122,30 @@ bool xmrig::RxDataset::init(const Buffer &seed, uint32_t numThreads, int priorit } +bool xmrig::RxDataset::isHugePages() const +{ + return m_memory && m_memory->isHugePages(); +} + + +bool xmrig::RxDataset::isOneGbPages() const +{ + return m_memory && m_memory->isOneGbPages(); +} + + +xmrig::HugePagesInfo xmrig::RxDataset::hugePages(bool cache) const +{ + auto pages = m_memory ? m_memory->hugePages() : HugePagesInfo(); + + if (cache && m_cache) { + pages += m_cache->hugePages(); + } + + return pages; +} + + size_t xmrig::RxDataset::size(bool cache) const { size_t size = 0; @@ -134,31 +162,6 @@ size_t xmrig::RxDataset::size(bool cache) const } -std::pair xmrig::RxDataset::hugePages(bool cache) const -{ - constexpr size_t twoMiB = 2U * 1024U * 1024U; - constexpr size_t oneGiB = 1024U * 1024U * 1024U; - constexpr size_t cacheSize = VirtualMemory::align(RxCache::maxSize(), twoMiB) / twoMiB; - size_t datasetPageSize = isOneGbPages() ? oneGiB : twoMiB; - size_t total = VirtualMemory::align(maxSize(), datasetPageSize) / datasetPageSize; - - uint32_t count = 0; - if (isHugePages() || isOneGbPages()) { - count += total; - } - - if (cache && m_cache) { - total += cacheSize; - - if (m_cache->isHugePages()) { - count += cacheSize; - } - } - - return { count, total }; -} - - void *xmrig::RxDataset::raw() const { return m_dataset ? randomx_get_dataset_memory(m_dataset) : nullptr; @@ -189,19 +192,12 @@ void xmrig::RxDataset::allocate(bool hugePages, bool oneGbPages) return; } - if (hugePages) { - m_flags = oneGbPages ? RANDOMX_FLAG_1GB_PAGES : RANDOMX_FLAG_LARGE_PAGES; - m_dataset = randomx_alloc_dataset(static_cast(m_flags)); + m_memory = new VirtualMemory(maxSize(), hugePages, oneGbPages, false, m_node); + m_dataset = randomx_create_dataset(m_memory->raw()); - if (oneGbPages && !m_dataset) { - LOG_ERR(CLEAR "%s" RED_BOLD_S "Failed to allocate RandomX dataset using 1GB pages", rx_tag()); - m_flags = RANDOMX_FLAG_LARGE_PAGES; - m_dataset = randomx_alloc_dataset(static_cast(m_flags)); - } - } - - if (!m_dataset) { - m_flags = RANDOMX_FLAG_DEFAULT; - m_dataset = randomx_alloc_dataset(static_cast(m_flags)); +# ifdef XMRIG_OS_LINUX + if (oneGbPages && !isOneGbPages()) { + LOG_ERR(CLEAR "%s" RED_BOLD_S "failed to allocate RandomX dataset using 1GB pages", rx_tag()); } +# endif } diff --git a/src/crypto/rx/RxDataset.h b/src/crypto/rx/RxDataset.h index ec9c7c8a6..e46a93c6f 100644 --- a/src/crypto/rx/RxDataset.h +++ b/src/crypto/rx/RxDataset.h @@ -30,6 +30,7 @@ #include "base/tools/Object.h" #include "crypto/common/Algorithm.h" +#include "crypto/common/HugePagesInfo.h" #include "crypto/randomx/configuration.h" #include "crypto/randomx/randomx.h" #include "crypto/rx/RxConfig.h" @@ -44,6 +45,7 @@ namespace xmrig class Buffer; class RxCache; +class VirtualMemory; class RxDataset @@ -51,19 +53,19 @@ class RxDataset public: XMRIG_DISABLE_COPY_MOVE_DEFAULT(RxDataset) - RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode); + RxDataset(bool hugePages, bool oneGbPages, bool cache, RxConfig::Mode mode, uint32_t node); RxDataset(RxCache *cache); ~RxDataset(); - inline bool isHugePages() const { return m_flags & RANDOMX_FLAG_LARGE_PAGES; } - inline bool isOneGbPages() const { return m_flags & RANDOMX_FLAG_1GB_PAGES; } inline randomx_dataset *get() const { return m_dataset; } inline RxCache *cache() const { return m_cache; } inline void setCache(RxCache *cache) { m_cache = cache; } bool init(const Buffer &seed, uint32_t numThreads, int priority); + bool isHugePages() const; + bool isOneGbPages() const; + HugePagesInfo hugePages(bool cache = true) const; size_t size(bool cache = true) const; - std::pair hugePages(bool cache = true) const; void *raw() const; void setRaw(const void *raw); @@ -73,9 +75,10 @@ private: void allocate(bool hugePages, bool oneGbPages); const RxConfig::Mode m_mode = RxConfig::FastMode; - int m_flags = 0; + const uint32_t m_node; randomx_dataset *m_dataset = nullptr; RxCache *m_cache = nullptr; + VirtualMemory *m_memory = nullptr; }; diff --git a/src/crypto/rx/RxNUMAStorage.cpp b/src/crypto/rx/RxNUMAStorage.cpp index a6d191481..b139a14d6 100644 --- a/src/crypto/rx/RxNUMAStorage.cpp +++ b/src/crypto/rx/RxNUMAStorage.cpp @@ -130,8 +130,10 @@ public: join(); - std::thread thread(allocateCache, this, m_nodeset.front(), hugePages); - thread.join(); + if (isCacheRequired()) { + std::thread thread(allocateCache, this, m_nodeset.front(), hugePages); + thread.join(); + } if (m_datasets.empty()) { m_datasets.insert({ m_nodeset.front(), new RxDataset(m_cache) }); @@ -139,7 +141,9 @@ public: LOG_WARN(CLEAR "%s" YELLOW_BOLD_S "failed to allocate RandomX datasets, switching to slow mode" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), Chrono::steadyMSecs() - ts); } else { - dataset(m_nodeset.front())->setCache(m_cache); + if (m_cache) { + dataset(m_nodeset.front())->setCache(m_cache); + } printAllocStatus(ts); } @@ -148,6 +152,22 @@ public: } + inline bool isCacheRequired() const + { + if (m_datasets.empty()) { + return true; + } + + for (const auto kv : m_datasets) { + if (kv.second->isOneGbPages()) { + return false; + } + } + + return true; + } + + inline void initDatasets(uint32_t threads, int priority) { uint64_t ts = Chrono::steadyMSecs(); @@ -174,13 +194,11 @@ public: } - inline std::pair hugePages() const + inline HugePagesInfo hugePages() const { - auto pages = m_cache->hugePages(); + HugePagesInfo pages; for (auto const &item : m_datasets) { - const auto p = item.second->hugePages(false); - pages.first += p.first; - pages.second += p.second; + pages += item.second->hugePages(); } return pages; @@ -198,7 +216,7 @@ private: return; } - auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode); + auto dataset = new RxDataset(hugePages, oneGbPages, false, RxConfig::FastMode, nodeId); if (!dataset->get()) { printSkipped(nodeId, "failed to allocate dataset"); @@ -218,7 +236,7 @@ private: bindToNUMANode(nodeId); - auto cache = new RxCache(hugePages); + auto cache = new RxCache(hugePages, nodeId); std::lock_guard lock(mutex); d_ptr->m_cache = cache; @@ -238,15 +256,14 @@ private: void printAllocStatus(RxDataset *dataset, uint32_t nodeId, uint64_t ts) { - const auto pages = dataset->hugePages(); - const double percent = pages.first == 0 ? 0.0 : static_cast(pages.first) / pages.second * 100.0; + const auto pages = dataset->hugePages(); LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %zu MB") " huge pages %s%3.0f%%" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), nodeId, - dataset->size() / oneMiB, - (pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S), - percent, + pages.size / oneMiB, + (pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S), + pages.percent(), Chrono::steadyMSecs() - ts ); } @@ -254,15 +271,14 @@ private: void printAllocStatus(RxCache *cache, uint32_t nodeId, uint64_t ts) { - const auto pages = cache->hugePages(); - const double percent = pages.first == 0 ? 0.0 : static_cast(pages.first) / pages.second * 100.0; + const auto pages = cache->hugePages(); LOG_INFO("%s" CYAN_BOLD("#%u ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%%" CLEAR " %sJIT" BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), nodeId, cache->size() / oneMiB, - (pages.first == pages.second ? GREEN_BOLD_S : RED_BOLD_S), - percent, + (pages.isFullyAllocated() ? GREEN_BOLD_S : RED_BOLD_S), + pages.percent(), cache->isJIT() ? GREEN_BOLD_S "+" : RED_BOLD_S "-", Chrono::steadyMSecs() - ts ); @@ -271,21 +287,15 @@ private: void printAllocStatus(uint64_t ts) { - size_t memory = m_cache->size(); - auto pages = hugePages(); - const double percent = pages.first == 0 ? 0.0 : static_cast(pages.first) / pages.second * 100.0; - - for (auto const &item : m_datasets) { - memory += item.second->size(false); - } + auto pages = hugePages(); LOG_INFO("%s" CYAN_BOLD("-- ") GREEN_BOLD("allocated") CYAN_BOLD(" %4zu MB") " huge pages %s%3.0f%% %u/%u" CLEAR BLACK_BOLD(" (%" PRIu64 " ms)"), rx_tag(), - memory / oneMiB, - (pages.first == pages.second ? GREEN_BOLD_S : (pages.first == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), - percent, - pages.first, - pages.second, + pages.size / oneMiB, + (pages.isFullyAllocated() ? GREEN_BOLD_S : (pages.allocated == 0 ? RED_BOLD_S : YELLOW_BOLD_S)), + pages.percent(), + pages.allocated, + pages.total, Chrono::steadyMSecs() - ts ); } @@ -326,6 +336,16 @@ xmrig::RxNUMAStorage::~RxNUMAStorage() } +xmrig::HugePagesInfo xmrig::RxNUMAStorage::hugePages() const +{ + if (!d_ptr->isAllocated()) { + return {}; + } + + return d_ptr->hugePages(); +} + + xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId) const { if (!d_ptr->isReady(job)) { @@ -336,16 +356,6 @@ xmrig::RxDataset *xmrig::RxNUMAStorage::dataset(const Job &job, uint32_t nodeId) } -std::pair xmrig::RxNUMAStorage::hugePages() const -{ - if (!d_ptr->isAllocated()) { - return { 0U, 0U }; - } - - return d_ptr->hugePages(); -} - - void xmrig::RxNUMAStorage::init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode, int priority) { d_ptr->setSeed(seed); diff --git a/src/crypto/rx/RxNUMAStorage.h b/src/crypto/rx/RxNUMAStorage.h index e7ea842fb..80626c9a6 100644 --- a/src/crypto/rx/RxNUMAStorage.h +++ b/src/crypto/rx/RxNUMAStorage.h @@ -51,8 +51,8 @@ public: ~RxNUMAStorage() override; protected: + HugePagesInfo hugePages() const override; RxDataset *dataset(const Job &job, uint32_t nodeId) const override; - std::pair hugePages() const override; void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override; private: diff --git a/src/crypto/rx/RxQueue.cpp b/src/crypto/rx/RxQueue.cpp index 8ca4a3791..b724e6af2 100644 --- a/src/crypto/rx/RxQueue.cpp +++ b/src/crypto/rx/RxQueue.cpp @@ -86,11 +86,11 @@ xmrig::RxDataset *xmrig::RxQueue::dataset(const Job &job, uint32_t nodeId) } -std::pair xmrig::RxQueue::hugePages() +xmrig::HugePagesInfo xmrig::RxQueue::hugePages() { std::lock_guard lock(m_mutex); - return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : std::pair(0U, 0U); + return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : HugePagesInfo(); } diff --git a/src/crypto/rx/RxQueue.h b/src/crypto/rx/RxQueue.h index 8a362b8ed..c83ae6d9a 100644 --- a/src/crypto/rx/RxQueue.h +++ b/src/crypto/rx/RxQueue.h @@ -29,6 +29,7 @@ #include "base/tools/Object.h" +#include "crypto/common/HugePagesInfo.h" #include "crypto/rx/RxConfig.h" #include "crypto/rx/RxSeed.h" @@ -83,7 +84,7 @@ public: bool isReady(const Job &job); RxDataset *dataset(const Job &job, uint32_t nodeId); - std::pair hugePages(); + HugePagesInfo hugePages(); void enqueue(const RxSeed &seed, const std::vector &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority); private: diff --git a/src/net/JobResults.cpp b/src/net/JobResults.cpp index 26f169521..c9c699f91 100644 --- a/src/net/JobResults.cpp +++ b/src/net/JobResults.cpp @@ -105,7 +105,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); + auto memory = new VirtualMemory(algorithm.l3(), false, false, false); uint8_t hash[32]{ 0 }; if (algorithm.family() == Algorithm::RANDOM_X) {