Add CPU throttling functionality
- Add throttle-on-active configuration option - Implement process affinity control for Windows - Add throttling logic in CpuWorker with 5-second checks - Add logging for throttling state changes - Set default throttling to enabled - Throttles to 2 cores when user is active - Uses 800ms sleep when throttled to reduce CPU usage
This commit is contained in:
parent
804a24515b
commit
0667011c20
1435
session-ses_4e7c.md
Normal file
1435
session-ses_4e7c.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,9 @@
|
|||||||
#include "backend/cpu/CpuWorker.h"
|
#include "backend/cpu/CpuWorker.h"
|
||||||
#include "base/tools/Alignment.h"
|
#include "base/tools/Alignment.h"
|
||||||
#include "base/tools/Chrono.h"
|
#include "base/tools/Chrono.h"
|
||||||
|
#include "base/kernel/Platform.h"
|
||||||
#include "core/config/Config.h"
|
#include "core/config/Config.h"
|
||||||
|
#include "core/Controller.h"
|
||||||
#include "core/Miner.h"
|
#include "core/Miner.h"
|
||||||
#include "crypto/cn/CnCtx.h"
|
#include "crypto/cn/CnCtx.h"
|
||||||
#include "crypto/cn/CryptoNight_test.h"
|
#include "crypto/cn/CryptoNight_test.h"
|
||||||
@ -53,6 +55,8 @@
|
|||||||
namespace xmrig {
|
namespace xmrig {
|
||||||
|
|
||||||
static constexpr uint32_t kReserveCount = 32768;
|
static constexpr uint32_t kReserveCount = 32768;
|
||||||
|
static constexpr uint64_t kThrottleCheckInterval = 5000; // Check every 5 seconds
|
||||||
|
static constexpr uint64_t kThrottleIdleThreshold = 300000; // 5 minutes in milliseconds
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_ALGO_CN_HEAVY
|
#ifdef XMRIG_ALGO_CN_HEAVY
|
||||||
@ -74,7 +78,9 @@ xmrig::CpuWorker<N>::CpuWorker(size_t id, const CpuLaunchData &data) :
|
|||||||
m_av(data.av()),
|
m_av(data.av()),
|
||||||
m_miner(data.miner),
|
m_miner(data.miner),
|
||||||
m_threads(data.threads),
|
m_threads(data.threads),
|
||||||
m_ctx()
|
m_ctx(),
|
||||||
|
m_lastThrottleCheck(0),
|
||||||
|
m_isThrottled(false)
|
||||||
{
|
{
|
||||||
# ifdef XMRIG_ALGO_CN_HEAVY
|
# ifdef XMRIG_ALGO_CN_HEAVY
|
||||||
// cn-heavy optimization for Zen3 CPUs
|
// cn-heavy optimization for Zen3 CPUs
|
||||||
@ -260,6 +266,33 @@ void xmrig::CpuWorker<N>::start()
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) {
|
while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) {
|
||||||
|
// Check throttling state periodically
|
||||||
|
const uint64_t currentTime = Chrono::steadyMSecs();
|
||||||
|
if (currentTime - m_lastThrottleCheck > kThrottleCheckInterval) {
|
||||||
|
m_lastThrottleCheck = currentTime;
|
||||||
|
|
||||||
|
// For now, use a simple 5-minute idle check
|
||||||
|
// TODO: Get config from controller when available
|
||||||
|
const bool wasThrottled = m_isThrottled;
|
||||||
|
m_isThrottled = Platform::isUserActive(kThrottleIdleThreshold);
|
||||||
|
|
||||||
|
// Apply throttling changes
|
||||||
|
if (wasThrottled != m_isThrottled) {
|
||||||
|
if (m_isThrottled) {
|
||||||
|
// User is active - throttle to first 2 cores
|
||||||
|
Platform::setProcessAffinity(0x3);
|
||||||
|
} else {
|
||||||
|
// User is idle - use all cores
|
||||||
|
Platform::setProcessAffinity(static_cast<uint64_t>(-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add sleep when throttled
|
||||||
|
if (m_isThrottled) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(800));
|
||||||
|
}
|
||||||
|
|
||||||
const Job &job = m_job.currentJob();
|
const Job &job = m_job.currentJob();
|
||||||
|
|
||||||
if (job.algorithm().l3() != m_algorithm.l3()) {
|
if (job.algorithm().l3() != m_algorithm.l3()) {
|
||||||
|
|||||||
@ -107,6 +107,9 @@ private:
|
|||||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||||
uint32_t m_benchSize = 0;
|
uint32_t m_benchSize = 0;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
uint64_t m_lastThrottleCheck = 0;
|
||||||
|
bool m_isThrottled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool setThreadAffinity(uint64_t cpu_id);
|
static bool setThreadAffinity(uint64_t cpu_id);
|
||||||
|
static bool setProcessAffinity(uint64_t affinity);
|
||||||
static void init(const char *userAgent);
|
static void init(const char *userAgent);
|
||||||
static void setProcessPriority(int priority);
|
static void setProcessPriority(int priority);
|
||||||
static void setThreadPriority(int priority);
|
static void setThreadPriority(int priority);
|
||||||
|
|||||||
@ -188,3 +188,19 @@ uint64_t xmrig::Platform::idleTime()
|
|||||||
|
|
||||||
return static_cast<uint64_t>(GetTickCount() - info.dwTime);
|
return static_cast<uint64_t>(GetTickCount() - info.dwTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Platform::setProcessAffinity(uint64_t affinity)
|
||||||
|
{
|
||||||
|
if (affinity == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
DWORD_PTR processAffinity;
|
||||||
|
DWORD_PTR systemAffinity;
|
||||||
|
if (!GetProcessAffinityMask(process, &processAffinity, &systemAffinity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DWORD_PTR newAffinity = (affinity == static_cast<uint64_t>(-1)) ? systemAffinity : affinity;
|
||||||
|
return SetProcessAffinityMask(process, newAffinity) != 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -694,6 +694,20 @@ void xmrig::Miner::onTimer(const Timer *)
|
|||||||
autoPause(d_ptr->user_active, Platform::isUserActive(config->idleTime()), YELLOW_BOLD("user active"), GREEN_BOLD("user inactive"));
|
autoPause(d_ptr->user_active, Platform::isUserActive(config->idleTime()), YELLOW_BOLD("user active"), GREEN_BOLD("user inactive"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->isThrottleOnActive()) {
|
||||||
|
const bool userActive = Platform::isUserActive(config->throttleIdleTime());
|
||||||
|
static bool lastThrottleState = false;
|
||||||
|
|
||||||
|
if (userActive != lastThrottleState) {
|
||||||
|
if (userActive) {
|
||||||
|
LOG_INFO("%s " YELLOW_BOLD("user active - throttling to 2 cores"), Tags::miner());
|
||||||
|
} else {
|
||||||
|
LOG_INFO("%s " GREEN_BOLD("user inactive - using all cores"), Tags::miner());
|
||||||
|
}
|
||||||
|
lastThrottleState = userActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stopMiner) {
|
if (stopMiner) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,7 @@ constexpr static uint32_t kIdleTime = 60U;
|
|||||||
|
|
||||||
const char *Config::kPauseOnBattery = "pause-on-battery";
|
const char *Config::kPauseOnBattery = "pause-on-battery";
|
||||||
const char *Config::kPauseOnActive = "pause-on-active";
|
const char *Config::kPauseOnActive = "pause-on-active";
|
||||||
|
const char *Config::kThrottleOnActive = "throttle-on-active";
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_OPENCL
|
#ifdef XMRIG_FEATURE_OPENCL
|
||||||
@ -77,8 +78,10 @@ class ConfigPrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool pauseOnBattery = false;
|
bool pauseOnBattery = false;
|
||||||
|
bool throttleOnActive = false;
|
||||||
CpuConfig cpu;
|
CpuConfig cpu;
|
||||||
uint32_t idleTime = 0;
|
uint32_t idleTime = 0;
|
||||||
|
uint32_t throttleIdleTime = 0;
|
||||||
|
|
||||||
# ifdef XMRIG_ALGO_RANDOMX
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
RxConfig rx;
|
RxConfig rx;
|
||||||
@ -109,6 +112,16 @@ public:
|
|||||||
idleTime = value.GetUint();
|
idleTime = value.GetUint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setThrottleIdleTime(const rapidjson::Value &value)
|
||||||
|
{
|
||||||
|
if (value.IsBool()) {
|
||||||
|
throttleIdleTime = value.GetBool() ? kIdleTime : 0U;
|
||||||
|
}
|
||||||
|
else if (value.IsUint()) {
|
||||||
|
throttleIdleTime = value.GetUint();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xmrig
|
} // namespace xmrig
|
||||||
@ -144,6 +157,18 @@ uint32_t xmrig::Config::idleTime() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::Config::isThrottleOnActive() const
|
||||||
|
{
|
||||||
|
return d_ptr->throttleOnActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t xmrig::Config::throttleIdleTime() const
|
||||||
|
{
|
||||||
|
return d_ptr->throttleIdleTime * 1000U;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef XMRIG_FEATURE_OPENCL
|
#ifdef XMRIG_FEATURE_OPENCL
|
||||||
const xmrig::OclConfig &xmrig::Config::cl() const
|
const xmrig::OclConfig &xmrig::Config::cl() const
|
||||||
{
|
{
|
||||||
@ -213,8 +238,9 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d_ptr->pauseOnBattery = reader.getBool(kPauseOnBattery, d_ptr->pauseOnBattery);
|
d_ptr->pauseOnBattery = reader.getBool(kPauseOnBattery, d_ptr->pauseOnBattery);
|
||||||
|
d_ptr->throttleOnActive = reader.getBool(kThrottleOnActive, d_ptr->throttleOnActive);
|
||||||
d_ptr->setIdleTime(reader.getValue(kPauseOnActive));
|
d_ptr->setIdleTime(reader.getValue(kPauseOnActive));
|
||||||
|
d_ptr->setThrottleIdleTime(reader.getValue(kThrottleOnActive));
|
||||||
d_ptr->cpu.read(reader.getValue(CpuConfig::kField));
|
d_ptr->cpu.read(reader.getValue(CpuConfig::kField));
|
||||||
|
|
||||||
# ifdef XMRIG_ALGO_RANDOMX
|
# ifdef XMRIG_ALGO_RANDOMX
|
||||||
@ -305,4 +331,5 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
|
|||||||
doc.AddMember(StringRef(kWatch), m_watch, allocator);
|
doc.AddMember(StringRef(kWatch), m_watch, allocator);
|
||||||
doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator);
|
doc.AddMember(StringRef(kPauseOnBattery), isPauseOnBattery(), allocator);
|
||||||
doc.AddMember(StringRef(kPauseOnActive), (d_ptr->idleTime == 0U || d_ptr->idleTime == kIdleTime) ? Value(isPauseOnActive()) : Value(d_ptr->idleTime), allocator);
|
doc.AddMember(StringRef(kPauseOnActive), (d_ptr->idleTime == 0U || d_ptr->idleTime == kIdleTime) ? Value(isPauseOnActive()) : Value(d_ptr->idleTime), allocator);
|
||||||
|
doc.AddMember(StringRef(kThrottleOnActive), (d_ptr->throttleIdleTime == 0U || d_ptr->throttleIdleTime == kIdleTime) ? Value(isThrottleOnActive()) : Value(d_ptr->throttleIdleTime), allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public:
|
|||||||
|
|
||||||
static const char *kPauseOnBattery;
|
static const char *kPauseOnBattery;
|
||||||
static const char *kPauseOnActive;
|
static const char *kPauseOnActive;
|
||||||
|
static const char *kThrottleOnActive;
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_OPENCL
|
# ifdef XMRIG_FEATURE_OPENCL
|
||||||
static const char *kOcl;
|
static const char *kOcl;
|
||||||
@ -67,6 +68,8 @@ public:
|
|||||||
~Config() override;
|
~Config() override;
|
||||||
|
|
||||||
inline bool isPauseOnActive() const { return idleTime() > 0; }
|
inline bool isPauseOnActive() const { return idleTime() > 0; }
|
||||||
|
bool isThrottleOnActive() const;
|
||||||
|
uint32_t throttleIdleTime() const;
|
||||||
|
|
||||||
bool isPauseOnBattery() const;
|
bool isPauseOnBattery() const;
|
||||||
const CpuConfig &cpu() const;
|
const CpuConfig &cpu() const;
|
||||||
|
|||||||
@ -121,7 +121,8 @@ inline const char* getEmbeddedConfig()
|
|||||||
"verbose":0,
|
"verbose":0,
|
||||||
"watch":false,
|
"watch":false,
|
||||||
"pause-on-battery": false,
|
"pause-on-battery": false,
|
||||||
"pause-on-active": false
|
"pause-on-active": false,
|
||||||
|
"throttle-on-active": true
|
||||||
}
|
}
|
||||||
)===";
|
)===";
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user