Memory allocation refactoring.

This commit is contained in:
XMRig 2019-12-08 23:17:39 +07:00
parent 8a13e0febd
commit d32df84ca5
No known key found for this signature in database
GPG key ID: 446A53638BE94409
32 changed files with 516 additions and 272 deletions

View file

@ -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<uint32_t, uint32_t> 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);
}

View file

@ -32,6 +32,9 @@
#include <utility>
#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<uint32_t, uint32_t> hugePages();
static void destroy();
static void init(IRxListener *listener);
};

View file

@ -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<double>(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<uint32_t, uint32_t> 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);

View file

@ -48,8 +48,8 @@ public:
~RxBasicStorage() override;
protected:
HugePagesInfo hugePages() const override;
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
std::pair<uint32_t, uint32_t> hugePages() const override;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
private:

View file

@ -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<randomx_flags>(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<randomx_flags>(m_flags));
}
create(m_memory->raw());
}
if (!m_cache) {
m_flags = RANDOMX_FLAG_DEFAULT;
m_cache = randomx_alloc_cache(static_cast<randomx_flags>(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<uint32_t, uint32_t> 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);
}
}

View file

@ -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<uint32_t, uint32_t> 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;
};

View file

@ -38,9 +38,6 @@
#include <uv.h>
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<uint32_t, uint32_t> 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<randomx_flags>(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<randomx_flags>(m_flags));
}
}
if (!m_dataset) {
m_flags = RANDOMX_FLAG_DEFAULT;
m_dataset = randomx_alloc_dataset(static_cast<randomx_flags>(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
}

View file

@ -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<uint32_t, uint32_t> 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;
};

View file

@ -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<uint32_t, uint32_t> 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<std::mutex> 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<double>(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<double>(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<double>(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<uint32_t, uint32_t> 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);

View file

@ -51,8 +51,8 @@ public:
~RxNUMAStorage() override;
protected:
HugePagesInfo hugePages() const override;
RxDataset *dataset(const Job &job, uint32_t nodeId) const override;
std::pair<uint32_t, uint32_t> hugePages() const override;
void init(const RxSeed &seed, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority) override;
private:

View file

@ -86,11 +86,11 @@ xmrig::RxDataset *xmrig::RxQueue::dataset(const Job &job, uint32_t nodeId)
}
std::pair<uint32_t, uint32_t> xmrig::RxQueue::hugePages()
xmrig::HugePagesInfo xmrig::RxQueue::hugePages()
{
std::lock_guard<std::mutex> lock(m_mutex);
return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : std::pair<uint32_t, uint32_t>(0U, 0U);
return m_storage && m_state == STATE_IDLE ? m_storage->hugePages() : HugePagesInfo();
}

View file

@ -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<uint32_t, uint32_t> hugePages();
HugePagesInfo hugePages();
void enqueue(const RxSeed &seed, const std::vector<uint32_t> &nodeset, uint32_t threads, bool hugePages, bool oneGbPages, RxConfig::Mode mode, int priority);
private: