Memory allocation refactoring.
This commit is contained in:
parent
8a13e0febd
commit
d32df84ca5
32 changed files with 516 additions and 272 deletions
50
src/crypto/common/HugePagesInfo.cpp
Normal file
50
src/crypto/common/HugePagesInfo.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
67
src/crypto/common/HugePagesInfo.h
Normal file
67
src/crypto/common/HugePagesInfo.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_HUGEPAGESINFO_H
|
||||
#define XMRIG_HUGEPAGESINFO_H
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
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<double>(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 */
|
103
src/crypto/common/LinuxMemory.cpp
Normal file
103
src/crypto/common/LinuxMemory.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//#include <iostream>
|
||||
|
||||
#include "crypto/common/LinuxMemory.h"
|
||||
#include "base/io/log/Log.h"
|
||||
#include "crypto/common/VirtualMemory.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
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<std::mutex> 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<size_t>(available) >= required) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return write_nr_hugepages(node, oneGbPages, std::max<size_t>(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;
|
||||
}
|
49
src/crypto/common/LinuxMemory.h
Normal file
49
src/crypto/common/LinuxMemory.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* XMRig
|
||||
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
|
||||
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
|
||||
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
|
||||
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
|
||||
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
|
||||
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
|
||||
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef XMRIG_LINUXMEMORY_H
|
||||
#define XMRIG_LINUXMEMORY_H
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
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 */
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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<std::mutex> 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)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
|
||||
#include "base/tools/Object.h"
|
||||
#include "crypto/common/HugePagesInfo.h"
|
||||
|
||||
|
||||
#include <bitset>
|
||||
|
@ -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<size_t, size_t> 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
|
||||
|
|
|
@ -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<uint8_t*>(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<uint8_t*>(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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue