feat: thread benchmark, GPU-aware idle mining, thread scaling fix
- Add pool mining thread benchmark: cycles through thread counts with 20s warmup + 10s measurement to find optimal setting for CPU - Add GPU-aware idle detection: GPU utilization >= 10% (video, games) treats system as active; toggle in mining tab header (default: on) Supports AMD sysfs, NVIDIA nvidia-smi, Intel freq ratio; -1 on macOS - Fix idle thread scaling: use getRequestedThreads() for immediate thread count instead of xmrig API threads_active which lags on restart - Apply active thread count on initial mining start when user is active - Skip idle mining adjustments while benchmark is running - Disable thread grid drag-to-select during benchmark - Add idle_gpu_aware setting with JSON persistence (default: true) - Add 7 i18n English strings for benchmark and GPU-aware tooltips
This commit is contained in:
@@ -845,6 +845,8 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["mining_idle_on_tooltip"] = "Disable idle mining";
|
||||
strings_["mining_idle_scale_on_tooltip"] = "Thread scaling: ON\nClick to switch to start/stop mode";
|
||||
strings_["mining_idle_scale_off_tooltip"] = "Start/stop mode: ON\nClick to switch to thread scaling mode";
|
||||
strings_["mining_idle_gpu_on_tooltip"] = "GPU-aware: ON\nGPU activity (video, games) prevents idle mining\nClick for unrestricted mode";
|
||||
strings_["mining_idle_gpu_off_tooltip"] = "Unrestricted: ON\nOnly keyboard/mouse input determines idle state\nClick to enable GPU-aware detection";
|
||||
strings_["mining_idle_threads_active_tooltip"] = "Threads when user is active";
|
||||
strings_["mining_idle_threads_idle_tooltip"] = "Threads when system is idle";
|
||||
strings_["mining_local_hashrate"] = "Local Hashrate";
|
||||
@@ -866,6 +868,11 @@ void I18n::loadBuiltinEnglish()
|
||||
strings_["mining_recent_payouts"] = "RECENT POOL PAYOUTS";
|
||||
strings_["mining_remove"] = "Remove";
|
||||
strings_["mining_reset_defaults"] = "Reset Defaults";
|
||||
strings_["mining_benchmark_tooltip"] = "Find optimal thread count for this CPU";
|
||||
strings_["mining_benchmark_testing"] = "Testing";
|
||||
strings_["mining_benchmark_cancel"] = "Cancel benchmark";
|
||||
strings_["mining_benchmark_result"] = "Optimal";
|
||||
strings_["mining_benchmark_dismiss"] = "Dismiss";
|
||||
strings_["mining_save_payout_address"] = "Save payout address";
|
||||
strings_["mining_save_pool_url"] = "Save pool URL";
|
||||
strings_["mining_saved_addresses"] = "Saved Addresses:";
|
||||
|
||||
@@ -688,5 +688,106 @@ int Platform::getSystemIdleSeconds()
|
||||
#endif
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// GPU utilization detection
|
||||
// ============================================================================
|
||||
|
||||
int Platform::getGpuUtilization()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Windows: read GPU utilization via SetupAPI / D3DKMT
|
||||
// Not all GPUs expose this; return -1 if unavailable.
|
||||
// Use a popen fallback: nvidia-smi for NVIDIA, or return -1.
|
||||
static bool s_tried_nvidia = false;
|
||||
static bool s_has_nvidia = false;
|
||||
if (!s_tried_nvidia) {
|
||||
s_tried_nvidia = true;
|
||||
FILE* f = _popen("where nvidia-smi 2>nul", "r");
|
||||
if (f) {
|
||||
char buf[256];
|
||||
s_has_nvidia = (fgets(buf, sizeof(buf), f) != nullptr);
|
||||
_pclose(f);
|
||||
}
|
||||
}
|
||||
if (s_has_nvidia) {
|
||||
FILE* f = _popen("nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits 2>nul", "r");
|
||||
if (f) {
|
||||
char buf[64];
|
||||
int util = -1;
|
||||
if (fgets(buf, sizeof(buf), f)) {
|
||||
util = atoi(buf);
|
||||
if (util < 0 || util > 100) util = -1;
|
||||
}
|
||||
_pclose(f);
|
||||
return util;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
#elif defined(__APPLE__)
|
||||
return -1;
|
||||
#else
|
||||
// Linux: try multiple GPU sysfs paths
|
||||
|
||||
// AMD: /sys/class/drm/card*/device/gpu_busy_percent
|
||||
{
|
||||
// Try card0 through card3
|
||||
char path[128];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/gpu_busy_percent", i);
|
||||
std::ifstream ifs(path);
|
||||
if (ifs.is_open()) {
|
||||
int val = -1;
|
||||
ifs >> val;
|
||||
if (val >= 0 && val <= 100)
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NVIDIA: nvidia-smi (binary may exist even without sysfs)
|
||||
{
|
||||
static bool s_tried = false;
|
||||
static bool s_has_nvidia_smi = false;
|
||||
if (!s_tried) {
|
||||
s_tried = true;
|
||||
FILE* f = popen("which nvidia-smi 2>/dev/null", "r");
|
||||
if (f) {
|
||||
char buf[256];
|
||||
s_has_nvidia_smi = (fgets(buf, sizeof(buf), f) != nullptr);
|
||||
pclose(f);
|
||||
}
|
||||
}
|
||||
if (s_has_nvidia_smi) {
|
||||
FILE* f = popen("nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits 2>/dev/null", "r");
|
||||
if (f) {
|
||||
char buf[64];
|
||||
int util = -1;
|
||||
if (fgets(buf, sizeof(buf), f)) {
|
||||
util = atoi(buf);
|
||||
if (util < 0 || util > 100) util = -1;
|
||||
}
|
||||
pclose(f);
|
||||
return util;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Intel: compare current vs max freq as a rough proxy
|
||||
{
|
||||
std::ifstream curF("/sys/class/drm/card0/gt_cur_freq_mhz");
|
||||
std::ifstream maxF("/sys/class/drm/card0/gt_max_freq_mhz");
|
||||
if (curF.is_open() && maxF.is_open()) {
|
||||
int cur = 0, mx = 0;
|
||||
curF >> cur;
|
||||
maxF >> mx;
|
||||
if (mx > 0)
|
||||
return std::min(100, (cur * 100) / mx);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace dragonx
|
||||
|
||||
@@ -131,6 +131,14 @@ public:
|
||||
* @return Seconds since last user input, or 0 on failure
|
||||
*/
|
||||
static int getSystemIdleSeconds();
|
||||
|
||||
/**
|
||||
* @brief Get GPU utilization percentage (0–100).
|
||||
* Linux: reads sysfs for AMD, /proc for NVIDIA.
|
||||
* Windows: queries PDH GPU engine counters.
|
||||
* @return GPU busy percent, or -1 if unavailable.
|
||||
*/
|
||||
static int getGpuUtilization();
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user