diff --git a/src/core/Config.cpp b/src/core/Config.cpp index fa6afdb4..f37e2e0f 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * 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 @@ -36,6 +37,10 @@ #include "rapidjson/prettywriter.h" #include "workers/CpuThread.h" +// for usage in Client::login to get_algo_perf +namespace xmrig { + Config* pconfig = nullptr; +}; static char affinity_tmp[20] = { 0 }; @@ -48,6 +53,11 @@ xmrig::Config::Config() : xmrig::CommonConfig(), m_maxCpuUsage(75), m_priority(-1) { + // not defined algo performance is considered to be 0 + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + m_algo_perf[pa] = 0; + } } @@ -111,18 +121,34 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("retry-pause", retryPause(), allocator); doc.AddMember("safe", m_safe, allocator); - if (threadsMode() == Advanced) { - Value threads(kArrayType); + // save extended "threads" based on m_threads + Value threads(kObjectType); + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + Value key(xmrig::Algorithm::perfAlgoName(pa), allocator); + if (threadsMode(pa) == Advanced) { + Value threads2(kArrayType); - for (const IThread *thread : m_threads.list) { - threads.PushBack(thread->toConfig(doc), allocator); + for (const IThread *thread : m_threads[pa].list) { + threads2.PushBack(thread->toConfig(doc), allocator); + } + + threads.AddMember(key, threads2, allocator); } + else { + threads.AddMember(key, threadsMode(pa) == Automatic ? Value(kNullType) : Value(threadsCount(pa)), allocator); + } + } + doc.AddMember("threads", threads, allocator); - doc.AddMember("threads", threads, allocator); - } - else { - doc.AddMember("threads", threadsMode() == Automatic ? Value(kNullType) : Value(threadsCount()), allocator); + // save "algo-perf" based on m_algo_perf + Value algo_perf(kObjectType); + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + Value key(xmrig::Algorithm::perfAlgoName(pa), allocator); + algo_perf.AddMember(key, Value(m_algo_perf[pa]), allocator); } + doc.AddMember("algo-perf", algo_perf, allocator); doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator); @@ -150,34 +176,36 @@ bool xmrig::Config::finalize() return false; } - if (!m_threads.cpu.empty()) { - m_threads.mode = Advanced; - const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; + // parse "threads" into m_threads + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + if (!m_threads[pa].cpu.empty()) { + m_threads[pa].mode = Advanced; + const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; - for (size_t i = 0; i < m_threads.cpu.size(); ++i) { - m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, softAES)); + for (size_t i = 0; i < m_threads[pa].cpu.size(); ++i) { + m_threads[pa].list.push_back(CpuThread::createFromData(i, xmrig::Algorithm(pa).algo(), m_threads[pa].cpu[i], m_priority, softAES)); + } + } else { + const AlgoVariant av = getAlgoVariant(); + m_threads[pa].mode = m_threads[pa].count ? Simple : Automatic; + + const size_t size = CpuThread::multiway(av) * cn_select_memory(xmrig::Algorithm(pa).algo()) / 1024; + + if (!m_threads[pa].count) { + m_threads[pa].count = Cpu::optimalThreadsCount(size, m_maxCpuUsage); + } + else if (m_safe) { + const size_t count = Cpu::optimalThreadsCount(size, m_maxCpuUsage); + if (m_threads[pa].count > count) { + m_threads[pa].count = count; + } + } + + for (size_t i = 0; i < m_threads[pa].count; ++i) { + m_threads[pa].list.push_back(CpuThread::createFromAV(i, xmrig::Algorithm(pa).algo(), av, m_threads[pa].mask, m_priority)); + } } - - return true; - } - - const AlgoVariant av = getAlgoVariant(); - m_threads.mode = m_threads.count ? Simple : Automatic; - - const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; - - if (!m_threads.count) { - m_threads.count = Cpu::optimalThreadsCount(size, m_maxCpuUsage); - } - else if (m_safe) { - const size_t count = Cpu::optimalThreadsCount(size, m_maxCpuUsage); - if (m_threads.count > count) { - m_threads.count = count; - } - } - - for (size_t i = 0; i < m_threads.count; ++i) { - m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority)); } return true; @@ -231,7 +259,7 @@ bool xmrig::Config::parseString(int key, const char *arg) case ThreadsKey: /* --threads */ if (strncmp(arg, "all", 3) == 0) { - m_threads.count = Cpu::threads(); + m_threads[m_algorithm.perf_algo()].count = Cpu::threads(); // sets default algo threads return true; } @@ -260,7 +288,7 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg) switch (key) { case CPUAffinityKey: /* --cpu-affinity */ if (arg) { - m_threads.mask = arg; + m_threads[m_algorithm.perf_algo()].mask = arg; // sets default algo threads } break; @@ -272,22 +300,49 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg) } +// parse specific perf algo (or generic) threads config +void xmrig::Config::parseThreadsJSON(const rapidjson::Value &threads, const xmrig::PerfAlgo pa) +{ + for (const rapidjson::Value &value : threads.GetArray()) { + if (!value.IsObject()) { + continue; + } + + if (value.HasMember("low_power_mode")) { + auto data = CpuThread::parse(value); + + if (data.valid) { + m_threads[pa].cpu.push_back(std::move(data)); + } + } + } +} + void xmrig::Config::parseJSON(const rapidjson::Document &doc) { const rapidjson::Value &threads = doc["threads"]; if (threads.IsArray()) { - for (const rapidjson::Value &value : threads.GetArray()) { - if (!value.IsObject()) { - continue; + // parse generic (old) threads + parseThreadsJSON(threads, m_algorithm.perf_algo()); + } else if (threads.IsObject()) { + // parse new specific perf algo threads + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + const rapidjson::Value &threads2 = threads[xmrig::Algorithm::perfAlgoName(pa)]; + if (threads2.IsArray()) { + parseThreadsJSON(threads2, pa); } + } + } - if (value.HasMember("low_power_mode")) { - auto data = CpuThread::parse(value); - - if (data.valid) { - m_threads.cpu.push_back(std::move(data)); - } + const rapidjson::Value &algo_perf = doc["algo-perf"]; + if (algo_perf.IsObject()) { + for (int a = 0; a != xmrig::PerfAlgo::PA_MAX; ++ a) { + const xmrig::PerfAlgo pa = static_cast(a); + const rapidjson::Value &key = algo_perf[xmrig::Algorithm::perfAlgoName(pa)]; + if (key.IsDouble()) { + m_algo_perf[pa] = key.GetDouble(); } } } @@ -299,7 +354,7 @@ bool xmrig::Config::parseInt(int key, int arg) switch (key) { case ThreadsKey: /* --threads */ if (arg >= 0 && arg < 1024) { - m_threads.count = arg; + m_threads[m_algorithm.perf_algo()].count = arg; // sets default algo threads } break; diff --git a/src/core/Config.h b/src/core/Config.h index f0f1404f..0bf7488d 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * 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 @@ -78,11 +79,25 @@ public: inline AesMode aesMode() const { return m_aesMode; } inline AlgoVariant algoVariant() const { return m_algoVariant; } inline bool isHugePages() const { return m_hugePages; } - inline const std::vector &threads() const { return m_threads.list; } inline int priority() const { return m_priority; } - inline int threadsCount() const { return m_threads.list.size(); } - inline int64_t affinity() const { return m_threads.mask; } - inline ThreadsMode threadsMode() const { return m_threads.mode; } + + // access to m_threads taking into accoun that it is now separated for each perf algo + inline const std::vector &threads(const xmrig::PerfAlgo pa = PA_INVALID) const { + return m_threads[pa == PA_INVALID ? m_algorithm.perf_algo() : pa].list; + } + inline int threadsCount(const xmrig::PerfAlgo pa = PA_INVALID) const { + return m_threads[pa == PA_INVALID ? m_algorithm.perf_algo() : pa].list.size(); + } + inline int64_t affinity(const xmrig::PerfAlgo pa = PA_INVALID) const { + return m_threads[pa == PA_INVALID ? m_algorithm.perf_algo() : pa].mask; + } + inline ThreadsMode threadsMode(const xmrig::PerfAlgo pa = PA_INVALID) const { + return m_threads[pa == PA_INVALID ? m_algorithm.perf_algo() : pa].mode; + } + + // access to perf algo results + inline float get_algo_perf(const xmrig::PerfAlgo pa) const { return m_algo_perf[pa]; } + inline void set_algo_perf(const xmrig::PerfAlgo pa, const float value) { m_algo_perf[pa] = value; } static Config *load(int argc, char **argv, IWatcherListener *listener); @@ -92,6 +107,8 @@ protected: bool parseString(int key, const char *arg) override; bool parseUint64(int key, uint64_t arg) override; void parseJSON(const rapidjson::Document &doc) override; + // parse specific perf algo (or generic) threads config + void parseThreadsJSON(const rapidjson::Value &threads, xmrig::PerfAlgo); private: bool parseInt(int key, int arg); @@ -120,9 +137,14 @@ private: bool m_safe; int m_maxCpuUsage; int m_priority; - Threads m_threads; + // threads config for each perf algo + Threads m_threads[xmrig::PerfAlgo::PA_MAX]; + // perf algo hashrate results + float m_algo_perf[xmrig::PerfAlgo::PA_MAX]; }; +extern Config* pconfig; + } /* namespace xmrig */ diff --git a/src/core/Controller.cpp b/src/core/Controller.cpp index ce73f037..a21c8ad9 100644 --- a/src/core/Controller.cpp +++ b/src/core/Controller.cpp @@ -6,6 +6,7 @@ * Copyright 2016 Jay D Dee * Copyright 2017-2018 XMR-Stak , * Copyright 2016-2018 XMRig , + * Copyright 2018 MoneroOcean , * * 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 @@ -96,7 +97,8 @@ int xmrig::Controller::init(int argc, char **argv) { Cpu::init(); - d_ptr->config = xmrig::Config::load(argc, argv, this); + // init pconfig global pointer to config + pconfig = d_ptr->config = xmrig::Config::load(argc, argv, this); if (!d_ptr->config) { return 1; }