From 7e1473d589fc23655e7c382200f4ed0a45049fcd Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 20:48:26 +0800 Subject: [PATCH 01/23] Add files via upload --- ForegroundBooster.cpp | 263 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 255 insertions(+), 8 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index b539205..7e7a070 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -16,12 +16,48 @@ #include #include #include +#include +#include #pragma comment(lib, "dwmapi.lib") #pragma comment(lib, "ntdll.lib") #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "user32.lib") +// --- 动态加载 API 定义 --- +typedef BOOL(WINAPI* SetThreadSelectedCpuSetsPtr)(HANDLE, const ULONG*, ULONG); + +// --- 全局变量新增 --- +std::mutex g_statsMutex; // 保护缓存的互斥锁 + +struct ThreadStats { + DWORD threadId; + FILETIME creationTime; + ULARGE_INTEGER lastKernelTime; + ULARGE_INTEGER lastUserTime; + ULARGE_INTEGER lastCheckTime; + double currentLoad; // 当前瞬时负载 (0.0 - 100.0) + double smoothedLoad; // 平滑后的负载 (EMA算法) + bool isMainThread; +}; + +struct ProcessStats { + DWORD processId; + std::map threads; + bool isInitialized; +}; + +// 核心缓存:PID -> 进程统计数据 +std::map g_processStatsCache; + +// 辅助函数:将 FILETIME 转换为 ULARGE_INTEGER +ULARGE_INTEGER FT2ULL(FILETIME ft) { + ULARGE_INTEGER ull; + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + return ull; +} + // --- 全局变量与常量 --- #define COLOR_INFO 11 #define COLOR_SUCCESS 10 @@ -697,22 +733,231 @@ void EventMessageLoopThread() if(g_hForegroundHook) UnhookWinEvent(g_hForegroundHook); } +void ThreadOptimizerThread() +{ + // 尝试加载 SetThreadSelectedCpuSets (Win10 1709+) + HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); + SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = + (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); + + while (true) + { + // 采样间隔:1秒。既能保证数据实时性,又不会占用过多CPU + std::this_thread::sleep_for(std::chrono::seconds(1)); + + DWORD currentPid = lastProcessId; + if (currentPid == 0) continue; + + // 1. 获取当前系统时间 (作为计算 CPU% 的分母) + FILETIME ftSystem; + GetSystemTimeAsFileTime(&ftSystem); + ULARGE_INTEGER now = FT2ULL(ftSystem); + + // 2. 拍摄线程快照 + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) continue; + + std::vector currentThreadIds; + THREADENTRY32 te32; + te32.dwSize = sizeof(THREADENTRY32); + + // --- 锁定缓存进行更新 --- + { + std::lock_guard lock(g_statsMutex); + ProcessStats& procStats = g_processStatsCache[currentPid]; + procStats.processId = currentPid; + + if (Thread32First(hSnapshot, &te32)) + { + do + { + if (te32.th32OwnerProcessID == currentPid) + { + DWORD tid = te32.th32ThreadID; + currentThreadIds.push_back(tid); + + // 如果是新发现的线程,初始化它 + if (procStats.threads.find(tid) == procStats.threads.end()) + { + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); + if (hThread) + { + ThreadStats ts = {}; + ts.threadId = tid; + ts.smoothedLoad = 0.0; + FILETIME ftExit, ftKernel, ftUser; + if (GetThreadTimes(hThread, &ts.creationTime, &ftExit, &ftKernel, &ftUser)) + { + ts.lastKernelTime = FT2ULL(ftKernel); + ts.lastUserTime = FT2ULL(ftUser); + ts.lastCheckTime = now; + procStats.threads[tid] = ts; + } + CloseHandle(hThread); + } + } + else + { + // 如果是已存在的线程,计算负载 + ThreadStats& ts = procStats.threads[tid]; + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); + if (hThread) + { + FILETIME ftCreation, ftExit, ftKernel, ftUser; + if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) + { + ULARGE_INTEGER k = FT2ULL(ftKernel); + ULARGE_INTEGER u = FT2ULL(ftUser); + + ULONGLONG timeDelta = now.QuadPart - ts.lastCheckTime.QuadPart; + ULONGLONG workDelta = (k.QuadPart - ts.lastKernelTime.QuadPart) + + (u.QuadPart - ts.lastUserTime.QuadPart); + + if (timeDelta > 0) + { + ts.currentLoad = (double)workDelta / (double)timeDelta * 100.0; + // 使用 EMA (指数移动平均) 平滑负载,权重 0.3 + ts.smoothedLoad = 0.3 * ts.currentLoad + 0.7 * ts.smoothedLoad; + } + + ts.lastKernelTime = k; + ts.lastUserTime = u; + ts.lastCheckTime = now; + } + CloseHandle(hThread); + } + } + } + } while (Thread32Next(hSnapshot, &te32)); + } + + // 清理该进程中已经退出的线程 + for (auto it = procStats.threads.begin(); it != procStats.threads.end(); ) + { + bool exists = false; + for (DWORD activeTid : currentThreadIds) { + if (activeTid == it->first) { exists = true; break; } + } + if (!exists) it = procStats.threads.erase(it); + else ++it; + } + + // --- 分析与应用策略 --- + if (!procStats.threads.empty()) + { + // 1. 寻找主线程 (创建时间最早) + ThreadStats* pMainThread = nullptr; + // 2. 寻找负载最重的线程 (SmoothedLoad 最高) + ThreadStats* pHeavyThread = nullptr; + + for (auto& pair : procStats.threads) + { + ThreadStats& t = pair.second; + + // 判定主线程 + if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) + { + pMainThread = &t; + } + + // 判定重负载线程 (排除主线程,避免冲突) + if (pMainThread && t.threadId != pMainThread->threadId) + { + if (pHeavyThread == nullptr || t.smoothedLoad > pHeavyThread->smoothedLoad) + { + pHeavyThread = &t; + } + } + } + + // 标记主线程 + if (pMainThread) pMainThread->isMainThread = true; + + // --- 执行优化策略 (仅当配置了 IdealCore 时) --- + if (settings.idealCore >= 0 && pMainThread) + { + // 策略 A: 主线程绑定到 IdealCore + HANDLE hMain = OpenThread(THREAD_SET_INFORMATION, FALSE, pMainThread->threadId); + if (hMain) + { + SetThreadIdealProcessor(hMain, settings.idealCore); + + // 如果支持 CPU Sets,也可以在这里设置 (示例: 绑定到 IdealCore) + // ULONG cpuSet[] = { (ULONG)settings.idealCore }; + // if (pSetThreadSelectedCpuSets) pSetThreadSelectedCpuSets(hMain, cpuSet, 1); + + CloseHandle(hMain); + } + + // 策略 B: 将最重的辅助线程“隔离”到另一个核心 (例如 IdealCore - 2) + // 这样可以避免渲染线程和主逻辑线程抢占同一个物理核 + if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) // 只有负载显著时才处理 + { + int heavyCore = settings.idealCore - 2; + if (heavyCore >= 0) + { + HANDLE hHeavy = OpenThread(THREAD_SET_INFORMATION, FALSE, pHeavyThread->threadId); + if (hHeavy) + { + SetThreadIdealProcessor(hHeavy, heavyCore); + CloseHandle(hHeavy); + } + } + } + } + } + } // 解锁 + + CloseHandle(hSnapshot); + } +} + void ProcessListCheckThread() { while (true) { std::this_thread::sleep_for(std::chrono::seconds(settings.processListInterval)); + + // --- 缓存清理逻辑 (新增) --- + { + std::lock_guard lock(g_statsMutex); + if (!g_processStatsCache.empty()) + { + // 获取当前所有运行中的 PID + std::set runningPids; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) + { + PROCESSENTRY32W pe32; + pe32.dwSize = sizeof(PROCESSENTRY32W); + if (Process32FirstW(hSnapshot, &pe32)) + { + do { runningPids.insert(pe32.th32ProcessID); } while (Process32NextW(hSnapshot, &pe32)); + } + CloseHandle(hSnapshot); + } + + // 遍历缓存,移除不在 runningPids 中的进程 + for (auto it = g_processStatsCache.begin(); it != g_processStatsCache.end(); ) + { + if (runningPids.find(it->first) == runningPids.end()) + { + Log("[缓存清理] 进程 PID %lu 已退出,清除其线程负载数据。\n", it->first); + it = g_processStatsCache.erase(it); + } + else + { + ++it; + } + } + } + } + // --------------------------- if (g_foregroundHasChanged.exchange(false)) { - // 只有在前台发生过变化时 才执行扫描和优先级重置 ScanAndResetIoPriorities(); } - else - { - // 如果前台没有变化 则跳过扫描 节省资源 - Log("[后台扫描] 前台未变化 跳过本次扫描\n"); - } } } @@ -761,10 +1006,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine std::thread t1(EventMessageLoopThread); std::thread t2(DwmThread); std::thread t3(ProcessListCheckThread); - + std::thread t4(ThreadOptimizerThread); // 新增的线程 + t1.join(); t2.join(); t3.join(); - + t4.join(); // 等待新线程 + return 0; } \ No newline at end of file From 4b43d9053eec85cbf82566e0502038baa0bfc0e4 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:16:11 +0800 Subject: [PATCH 02/23] Add files via upload --- ForegroundBooster.cpp | 113 +++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 52 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 7e7a070..55b8d84 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -735,20 +735,25 @@ void EventMessageLoopThread() void ThreadOptimizerThread() { - // 尝试加载 SetThreadSelectedCpuSets (Win10 1709+) + // 动态加载 SetThreadSelectedCpuSets (Win10 1709+ 支持) HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); + if (!pSetThreadSelectedCpuSets) + { + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 SetThreadSelectedCpuSets API,将仅使用 IdealProcessor。\n"); + } + while (true) { - // 采样间隔:1秒。既能保证数据实时性,又不会占用过多CPU + // 采样间隔:1秒 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; if (currentPid == 0) continue; - // 1. 获取当前系统时间 (作为计算 CPU% 的分母) + // 1. 获取当前系统时间 FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); @@ -776,7 +781,7 @@ void ThreadOptimizerThread() DWORD tid = te32.th32ThreadID; currentThreadIds.push_back(tid); - // 如果是新发现的线程,初始化它 + // 初始化或更新线程数据 if (procStats.threads.find(tid) == procStats.threads.end()) { HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); @@ -798,7 +803,6 @@ void ThreadOptimizerThread() } else { - // 如果是已存在的线程,计算负载 ThreadStats& ts = procStats.threads[tid]; HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); if (hThread) @@ -816,7 +820,6 @@ void ThreadOptimizerThread() if (timeDelta > 0) { ts.currentLoad = (double)workDelta / (double)timeDelta * 100.0; - // 使用 EMA (指数移动平均) 平滑负载,权重 0.3 ts.smoothedLoad = 0.3 * ts.currentLoad + 0.7 * ts.smoothedLoad; } @@ -845,53 +848,54 @@ void ThreadOptimizerThread() // --- 分析与应用策略 --- if (!procStats.threads.empty()) { - // 1. 寻找主线程 (创建时间最早) ThreadStats* pMainThread = nullptr; - // 2. 寻找负载最重的线程 (SmoothedLoad 最高) ThreadStats* pHeavyThread = nullptr; for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; - - // 判定主线程 if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) - { pMainThread = &t; - } - // 判定重负载线程 (排除主线程,避免冲突) if (pMainThread && t.threadId != pMainThread->threadId) { if (pHeavyThread == nullptr || t.smoothedLoad > pHeavyThread->smoothedLoad) - { pHeavyThread = &t; - } } } - // 标记主线程 if (pMainThread) pMainThread->isMainThread = true; - // --- 执行优化策略 (仅当配置了 IdealCore 时) --- + // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread) { - // 策略 A: 主线程绑定到 IdealCore HANDLE hMain = OpenThread(THREAD_SET_INFORMATION, FALSE, pMainThread->threadId); if (hMain) { + // 1. 设置理想核心 (软性建议) SetThreadIdealProcessor(hMain, settings.idealCore); - // 如果支持 CPU Sets,也可以在这里设置 (示例: 绑定到 IdealCore) - // ULONG cpuSet[] = { (ULONG)settings.idealCore }; - // if (pSetThreadSelectedCpuSets) pSetThreadSelectedCpuSets(hMain, cpuSet, 1); + // 2. 设置 CPU Sets (硬性建议) - 修复部分 + if (pSetThreadSelectedCpuSets) + { + ULONG cpuSet[] = { (ULONG)settings.idealCore }; + // 将主线程限制在 IdealCore 上运行 + if (pSetThreadSelectedCpuSets(hMain, cpuSet, 1)) + { + // 仅在首次成功时记录,避免刷屏 + static DWORD lastReportedTid = 0; + if (lastReportedTid != pMainThread->threadId) { + LogColor(COLOR_SUCCESS, " -> [优化] 已为主线程 %lu 设置 CPU Set: %d\n", pMainThread->threadId, settings.idealCore); + lastReportedTid = pMainThread->threadId; + } + } + } CloseHandle(hMain); } - // 策略 B: 将最重的辅助线程“隔离”到另一个核心 (例如 IdealCore - 2) - // 这样可以避免渲染线程和主逻辑线程抢占同一个物理核 - if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) // 只有负载显著时才处理 + // 策略 B: 隔离重负载线程 + if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) { int heavyCore = settings.idealCore - 2; if (heavyCore >= 0) @@ -900,13 +904,14 @@ void ThreadOptimizerThread() if (hHeavy) { SetThreadIdealProcessor(hHeavy, heavyCore); + // 对重负载线程也可以设置 CPU Sets,视需求而定,这里暂只设置理想核以保持灵活性 CloseHandle(hHeavy); } } } } } - } // 解锁 + } CloseHandle(hSnapshot); } @@ -918,44 +923,48 @@ void ProcessListCheckThread() { std::this_thread::sleep_for(std::chrono::seconds(settings.processListInterval)); - // --- 缓存清理逻辑 (新增) --- + // 检查前台是否发生变化 + if (g_foregroundHasChanged.exchange(false)) { - std::lock_guard lock(g_statsMutex); - if (!g_processStatsCache.empty()) + LogColor(COLOR_INFO, "[状态变更] 前台进程已切换,正在执行维护任务...\n"); + + // --- 1. 清理已退出进程的缓存数据 (仅在此处执行) --- { - // 获取当前所有运行中的 PID - std::set runningPids; - HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (hSnapshot != INVALID_HANDLE_VALUE) + std::lock_guard lock(g_statsMutex); + if (!g_processStatsCache.empty()) { - PROCESSENTRY32W pe32; - pe32.dwSize = sizeof(PROCESSENTRY32W); - if (Process32FirstW(hSnapshot, &pe32)) + // 获取当前所有运行中的 PID + std::set runningPids; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) { - do { runningPids.insert(pe32.th32ProcessID); } while (Process32NextW(hSnapshot, &pe32)); + PROCESSENTRY32W pe32; + pe32.dwSize = sizeof(PROCESSENTRY32W); + if (Process32FirstW(hSnapshot, &pe32)) + { + do { runningPids.insert(pe32.th32ProcessID); } while (Process32NextW(hSnapshot, &pe32)); + } + CloseHandle(hSnapshot); } - CloseHandle(hSnapshot); - } - // 遍历缓存,移除不在 runningPids 中的进程 - for (auto it = g_processStatsCache.begin(); it != g_processStatsCache.end(); ) - { - if (runningPids.find(it->first) == runningPids.end()) + // 遍历缓存,移除不在 runningPids 中的进程 + for (auto it = g_processStatsCache.begin(); it != g_processStatsCache.end(); ) { - Log("[缓存清理] 进程 PID %lu 已退出,清除其线程负载数据。\n", it->first); - it = g_processStatsCache.erase(it); - } - else - { - ++it; + if (runningPids.find(it->first) == runningPids.end()) + { + LogColor(COLOR_DEFAULT, " -> [缓存清理] 进程 PID %lu 已退出,清除其线程负载数据。\n", it->first); + it = g_processStatsCache.erase(it); + } + else + { + ++it; + } } } } - } - // --------------------------- + // -------------------------------------------------- - if (g_foregroundHasChanged.exchange(false)) - { + // --- 2. 扫描并重置后台进程优先级 --- ScanAndResetIoPriorities(); } } From a96e7225c1482241da67a1bb911def989be2ac81 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:23:32 +0800 Subject: [PATCH 03/23] Add files via upload --- ForegroundBooster.cpp | 140 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 20 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 55b8d84..0c9c1eb 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -733,32 +733,127 @@ void EventMessageLoopThread() if(g_hForegroundHook) UnhookWinEvent(g_hForegroundHook); } +// --- 新增:CPU Sets API 定义与辅助函数 --- + +// 定义 SYSTEM_CPU_SET_INFORMATION 结构 (防止旧版 SDK 缺失) +// 如果您的编译环境提示重定义,请注释掉此结构体 +typedef struct _SYSTEM_CPU_SET_INFORMATION { + DWORD Size; + DWORD Type; // CpuSetInformation + struct { + DWORD Id; + WORD Group; + BYTE LogicalProcessorIndex; + BYTE CoreIndex; + BYTE LastLevelCacheIndex; + BYTE NumaNodeIndex; + BYTE EfficiencyClass; + union { + BYTE AllFlags; + struct { + BYTE Parked : 1; + BYTE Allocated : 1; + BYTE AllocatedToTargetProcess : 1; + BYTE RealTime : 1; + BYTE ReservedFlags : 4; + } DUMMYSTRUCTNAME; + } DUMMYUNIONNAME; + union { + DWORD Reserved; + BYTE SchedulingClass; + }; + DWORD64 AllocationTag; + } CpuSet; +} SYSTEM_CPU_SET_INFORMATION, *PSYSTEM_CPU_SET_INFORMATION; + +using GetSystemCpuSetInformationPtr = BOOL(WINAPI*)(PSYSTEM_CPU_SET_INFORMATION, ULONG, PULONG, HANDLE, ULONG); +using SetThreadSelectedCpuSetsPtr = BOOL(WINAPI*)(HANDLE, const ULONG*, ULONG); + +// 辅助函数:将逻辑核心索引 (如 19) 转换为系统 CPU Set ID +// 如果失败返回 0 +ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation) { + if (!pGetSystemCpuSetInformation) return 0; + + ULONG returnLength = 0; + // 第一次调用获取所需缓冲区大小 + pGetSystemCpuSetInformation(NULL, 0, &returnLength, GetCurrentProcess(), 0); + + if (returnLength == 0) return 0; + + std::vector buffer(returnLength); + PSYSTEM_CPU_SET_INFORMATION pInfo = (PSYSTEM_CPU_SET_INFORMATION)buffer.data(); + + // 第二次调用获取实际数据 + if (!pGetSystemCpuSetInformation(pInfo, returnLength, &returnLength, GetCurrentProcess(), 0)) { + return 0; + } + + // 遍历缓冲区 + BYTE* ptr = buffer.data(); + BYTE* end = ptr + returnLength; + + while (ptr < end) { + PSYSTEM_CPU_SET_INFORMATION entry = (PSYSTEM_CPU_SET_INFORMATION)ptr; + + // Type 0 是 CpuSetInformation + if (entry->Type == 0) { // CpuSetInformation + if (entry->CpuSet.LogicalProcessorIndex == logicalIndex) { + return entry->CpuSet.Id; // 找到对应的 ID + } + } + + // 移动到下一个条目 (注意:必须使用 entry->Size,因为结构体大小可能随系统版本变化) + if (entry->Size == 0) break; // 防止死循环 + ptr += entry->Size; + } + + return 0; // 未找到 +} + void ThreadOptimizerThread() { - // 动态加载 SetThreadSelectedCpuSets (Win10 1709+ 支持) HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); + // 加载 API SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); + GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = + (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); - if (!pSetThreadSelectedCpuSets) + if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 SetThreadSelectedCpuSets API,将仅使用 IdealProcessor。\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),将仅使用 IdealProcessor。\n"); + } + + // --- 预先解析 IdealCore 对应的 CpuSetId --- + ULONG targetCpuSetId = 0; + ULONG heavyCpuSetId = 0; // 用于重负载线程 (IdealCore - 1) + + if (settings.idealCore >= 0 && pGetSystemCpuSetInformation) { + targetCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); + if (targetCpuSetId != 0) { + LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d 映射为 CPU Set ID: %lu\n", settings.idealCore, targetCpuSetId); + } else { + LogColor(COLOR_ERROR, "[CPU Sets] 错误: 无法找到逻辑核心 %d 的 CPU Set ID。\n", settings.idealCore); + } + + // 尝试解析 IdealCore - 1 (用于隔离重负载线程) + if (settings.idealCore > 0) { + heavyCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)(settings.idealCore - 1), pGetSystemCpuSetInformation); + } } + // ------------------------------------------- while (true) { - // 采样间隔:1秒 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; if (currentPid == 0) continue; - // 1. 获取当前系统时间 FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); - // 2. 拍摄线程快照 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot == INVALID_HANDLE_VALUE) continue; @@ -766,7 +861,6 @@ void ThreadOptimizerThread() THREADENTRY32 te32; te32.dwSize = sizeof(THREADENTRY32); - // --- 锁定缓存进行更新 --- { std::lock_guard lock(g_statsMutex); ProcessStats& procStats = g_processStatsCache[currentPid]; @@ -781,7 +875,6 @@ void ThreadOptimizerThread() DWORD tid = te32.th32ThreadID; currentThreadIds.push_back(tid); - // 初始化或更新线程数据 if (procStats.threads.find(tid) == procStats.threads.end()) { HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); @@ -834,7 +927,7 @@ void ThreadOptimizerThread() } while (Thread32Next(hSnapshot, &te32)); } - // 清理该进程中已经退出的线程 + // 清理已退出的线程 for (auto it = procStats.threads.begin(); it != procStats.threads.end(); ) { bool exists = false; @@ -869,23 +962,23 @@ void ThreadOptimizerThread() // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread) { - HANDLE hMain = OpenThread(THREAD_SET_INFORMATION, FALSE, pMainThread->threadId); + HANDLE hMain = OpenThread(THREAD_SET_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, pMainThread->threadId); if (hMain) { // 1. 设置理想核心 (软性建议) SetThreadIdealProcessor(hMain, settings.idealCore); - // 2. 设置 CPU Sets (硬性建议) - 修复部分 - if (pSetThreadSelectedCpuSets) + // 2. 设置 CPU Sets (硬性建议) - 使用正确的 ID + if (pSetThreadSelectedCpuSets && targetCpuSetId != 0) { - ULONG cpuSet[] = { (ULONG)settings.idealCore }; - // 将主线程限制在 IdealCore 上运行 - if (pSetThreadSelectedCpuSets(hMain, cpuSet, 1)) + ULONG cpuSetIds[] = { targetCpuSetId }; + // 注意:这里传入的是 ID 数组,而不是逻辑核心索引 + if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - // 仅在首次成功时记录,避免刷屏 static DWORD lastReportedTid = 0; if (lastReportedTid != pMainThread->threadId) { - LogColor(COLOR_SUCCESS, " -> [优化] 已为主线程 %lu 设置 CPU Set: %d\n", pMainThread->threadId, settings.idealCore); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)\n", + pMainThread->threadId, targetCpuSetId, settings.idealCore); lastReportedTid = pMainThread->threadId; } } @@ -897,14 +990,21 @@ void ThreadOptimizerThread() // 策略 B: 隔离重负载线程 if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) { - int heavyCore = settings.idealCore - 2; + int heavyCore = settings.idealCore - 1; if (heavyCore >= 0) { - HANDLE hHeavy = OpenThread(THREAD_SET_INFORMATION, FALSE, pHeavyThread->threadId); + HANDLE hHeavy = OpenThread(THREAD_SET_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, pHeavyThread->threadId); if (hHeavy) { SetThreadIdealProcessor(hHeavy, heavyCore); - // 对重负载线程也可以设置 CPU Sets,视需求而定,这里暂只设置理想核以保持灵活性 + + // 如果我们也想为重负载线程设置 CPU Sets + if (pSetThreadSelectedCpuSets && heavyCpuSetId != 0) + { + ULONG cpuSetIds[] = { heavyCpuSetId }; + pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1); + } + CloseHandle(hHeavy); } } From 7b8067e2f7b0107833d2065931ab388d31274835 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:26:36 +0800 Subject: [PATCH 04/23] Add files via upload --- ForegroundBooster.cpp | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 0c9c1eb..e659d4a 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -734,38 +734,6 @@ void EventMessageLoopThread() } // --- 新增:CPU Sets API 定义与辅助函数 --- - -// 定义 SYSTEM_CPU_SET_INFORMATION 结构 (防止旧版 SDK 缺失) -// 如果您的编译环境提示重定义,请注释掉此结构体 -typedef struct _SYSTEM_CPU_SET_INFORMATION { - DWORD Size; - DWORD Type; // CpuSetInformation - struct { - DWORD Id; - WORD Group; - BYTE LogicalProcessorIndex; - BYTE CoreIndex; - BYTE LastLevelCacheIndex; - BYTE NumaNodeIndex; - BYTE EfficiencyClass; - union { - BYTE AllFlags; - struct { - BYTE Parked : 1; - BYTE Allocated : 1; - BYTE AllocatedToTargetProcess : 1; - BYTE RealTime : 1; - BYTE ReservedFlags : 4; - } DUMMYSTRUCTNAME; - } DUMMYUNIONNAME; - union { - DWORD Reserved; - BYTE SchedulingClass; - }; - DWORD64 AllocationTag; - } CpuSet; -} SYSTEM_CPU_SET_INFORMATION, *PSYSTEM_CPU_SET_INFORMATION; - using GetSystemCpuSetInformationPtr = BOOL(WINAPI*)(PSYSTEM_CPU_SET_INFORMATION, ULONG, PULONG, HANDLE, ULONG); using SetThreadSelectedCpuSetsPtr = BOOL(WINAPI*)(HANDLE, const ULONG*, ULONG); From 11934bef27dd7f65bb210041f9137a10d3b5cf69 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 21:57:06 +0800 Subject: [PATCH 05/23] Add files via upload --- ForegroundBooster.cpp | 162 +++++++++++++++++++++++++++++------------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index e659d4a..0bad481 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -39,6 +39,10 @@ struct ThreadStats { double currentLoad; // 当前瞬时负载 (0.0 - 100.0) double smoothedLoad; // 平滑后的负载 (EMA算法) bool isMainThread; + // --- 新增部分开始 --- + bool hasCpuSets; // 标记此线程是否被设置了 CPU Sets + ULONG assignedCpuSetId; // 如果设置了,记录分配的 CPU Set ID + // --- 新增部分结束 --- }; struct ProcessStats { @@ -781,7 +785,6 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation void ThreadOptimizerThread() { HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); - // 加载 API SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = @@ -793,20 +796,24 @@ void ThreadOptimizerThread() } // --- 预先解析 IdealCore 对应的 CpuSetId --- - ULONG targetCpuSetId = 0; - ULONG heavyCpuSetId = 0; // 用于重负载线程 (IdealCore - 1) + ULONG idealCoreCpuSetId = 0; // IdealCore 对应的 CPU Set ID + ULONG mainThreadFallbackCpuSetId = 0; // IdealCore - 2 对应的 CPU Set ID if (settings.idealCore >= 0 && pGetSystemCpuSetInformation) { - targetCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); - if (targetCpuSetId != 0) { - LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d 映射为 CPU Set ID: %lu\n", settings.idealCore, targetCpuSetId); + idealCoreCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); + if (idealCoreCpuSetId != 0) { + LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d 映射为 CPU Set ID: %lu\n", settings.idealCore, idealCoreCpuSetId); } else { LogColor(COLOR_ERROR, "[CPU Sets] 错误: 无法找到逻辑核心 %d 的 CPU Set ID。\n", settings.idealCore); } - // 尝试解析 IdealCore - 1 (用于隔离重负载线程) - if (settings.idealCore > 0) { - heavyCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)(settings.idealCore - 1), pGetSystemCpuSetInformation); + if (settings.idealCore >= 2) { // 确保 IdealCore - 2 是有效核心 + mainThreadFallbackCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)(settings.idealCore - 2), pGetSystemCpuSetInformation); + if (mainThreadFallbackCpuSetId != 0) { + LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d (IdealCore-2) 映射为 CPU Set ID: %lu\n", settings.idealCore - 2, mainThreadFallbackCpuSetId); + } else { + LogColor(COLOR_ERROR, "[CPU Sets] 错误: 无法找到逻辑核心 %d (IdealCore-2) 的 CPU Set ID。\n", settings.idealCore - 2); + } } } // ------------------------------------------- @@ -851,6 +858,8 @@ void ThreadOptimizerThread() ThreadStats ts = {}; ts.threadId = tid; ts.smoothedLoad = 0.0; + ts.hasCpuSets = false; // 初始化为未设置 + ts.assignedCpuSetId = 0; FILETIME ftExit, ftKernel, ftUser; if (GetThreadTimes(hThread, &ts.creationTime, &ftExit, &ftKernel, &ftUser)) { @@ -902,23 +911,36 @@ void ThreadOptimizerThread() for (DWORD activeTid : currentThreadIds) { if (activeTid == it->first) { exists = true; break; } } - if (!exists) it = procStats.threads.erase(it); - else ++it; + if (!exists) { + // 如果线程退出,确保其 CPU Sets 状态被清除 + if (it->second.hasCpuSets) { + LogColor(COLOR_DEFAULT, " -> [优化] 线程 %lu 已退出,其 CPU Sets 状态已清除。\n", it->first); + } + it = procStats.threads.erase(it); + } + else { + ++it; + } } // --- 分析与应用策略 --- if (!procStats.threads.empty()) { ThreadStats* pMainThread = nullptr; - ThreadStats* pHeavyThread = nullptr; + ThreadStats* pHeavyThread = nullptr; // 负载最重的非主线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) pMainThread = &t; - - if (pMainThread && t.threadId != pMainThread->threadId) + } + + // 再次遍历,寻找最重负载的非主线程 + for (auto& pair : procStats.threads) + { + ThreadStats& t = pair.second; + if (pMainThread && t.threadId != pMainThread->threadId) // 排除主线程 { if (pHeavyThread == nullptr || t.smoothedLoad > pHeavyThread->smoothedLoad) pHeavyThread = &t; @@ -927,53 +949,97 @@ void ThreadOptimizerThread() if (pMainThread) pMainThread->isMainThread = true; - // --- 执行优化策略 --- - if (settings.idealCore >= 0 && pMainThread) + // --- 执行优化策略 (仅当配置了 IdealCore 且 CPU Sets API 可用时) --- + if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { - HANDLE hMain = OpenThread(THREAD_SET_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, pMainThread->threadId); - if (hMain) + // 1. 处理最重负载线程 (pHeavyThread) + if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) // 只有负载显著时才处理 { - // 1. 设置理想核心 (软性建议) - SetThreadIdealProcessor(hMain, settings.idealCore); - - // 2. 设置 CPU Sets (硬性建议) - 使用正确的 ID - if (pSetThreadSelectedCpuSets && targetCpuSetId != 0) + // 如果最重负载线程不是 IdealCoreCpuSetId,或者之前分配了其他 ID,则重新设置 + if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { - ULONG cpuSetIds[] = { targetCpuSetId }; - // 注意:这里传入的是 ID 数组,而不是逻辑核心索引 - if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) + // 清空之前设置了 CPU Sets 的其他线程 (除了主线程) + for (auto& pair : procStats.threads) { + ThreadStats& t = pair.second; + if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { + HANDLE hOther = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, t.threadId); + if (hOther) { + pSetThreadSelectedCpuSets(hOther, NULL, 0); // 清空 CPU Sets + LogColor(COLOR_DEFAULT, " -> [优化] 清空线程 %lu 的 CPU Sets (原分配: %lu)。\n", t.threadId, t.assignedCpuSetId); + t.hasCpuSets = false; + t.assignedCpuSetId = 0; + CloseHandle(hOther); + } + } + } + + // 为当前最重负载线程设置 CPU Sets + HANDLE hHeavy = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pHeavyThread->threadId); + if (hHeavy) { - static DWORD lastReportedTid = 0; - if (lastReportedTid != pMainThread->threadId) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)\n", - pMainThread->threadId, targetCpuSetId, settings.idealCore); - lastReportedTid = pMainThread->threadId; + ULONG cpuSetIds[] = { idealCoreCpuSetId }; + if (pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1)) + { + LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (最重负载) 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", + pHeavyThread->threadId, idealCoreCpuSetId, settings.idealCore); + pHeavyThread->hasCpuSets = true; + pHeavyThread->assignedCpuSetId = idealCoreCpuSetId; } + CloseHandle(hHeavy); } } - - CloseHandle(hMain); - } - // 策略 B: 隔离重负载线程 - if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) - { - int heavyCore = settings.idealCore - 1; - if (heavyCore >= 0) + // 2. 处理主线程 (如果最重负载线程不是主线程) + // 将主线程的 CPU Sets 设置为 IdealCore - 2 + if (pMainThread->assignedCpuSetId != mainThreadFallbackCpuSetId && mainThreadFallbackCpuSetId != 0) { - HANDLE hHeavy = OpenThread(THREAD_SET_INFORMATION | THREAD_QUERY_LIMITED_INFORMATION, FALSE, pHeavyThread->threadId); - if (hHeavy) + HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pMainThread->threadId); + if (hMain) { - SetThreadIdealProcessor(hHeavy, heavyCore); - - // 如果我们也想为重负载线程设置 CPU Sets - if (pSetThreadSelectedCpuSets && heavyCpuSetId != 0) + ULONG cpuSetIds[] = { mainThreadFallbackCpuSetId }; + if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - ULONG cpuSetIds[] = { heavyCpuSetId }; - pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", + pMainThread->threadId, mainThreadFallbackCpuSetId, settings.idealCore - 2); + pMainThread->hasCpuSets = true; + pMainThread->assignedCpuSetId = mainThreadFallbackCpuSetId; + } + CloseHandle(hMain); + } + } + } + else // 如果没有显著的重负载非主线程,或者重负载线程就是主线程 + { + // 清空所有非主线程的 CPU Sets + for (auto& pair : procStats.threads) { + ThreadStats& t = pair.second; + if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { + HANDLE hOther = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, t.threadId); + if (hOther) { + pSetThreadSelectedCpuSets(hOther, NULL, 0); // 清空 CPU Sets + LogColor(COLOR_DEFAULT, " -> [优化] 清空线程 %lu 的 CPU Sets (原分配: %lu)。\n", t.threadId, t.assignedCpuSetId); + t.hasCpuSets = false; + t.assignedCpuSetId = 0; + CloseHandle(hOther); } + } + } - CloseHandle(hHeavy); + // 将主线程的 CPU Sets 设置为 IdealCore + if (!pMainThread->hasCpuSets || pMainThread->assignedCpuSetId != idealCoreCpuSetId) + { + HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pMainThread->threadId); + if (hMain) + { + ULONG cpuSetIds[] = { idealCoreCpuSetId }; + if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) + { + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", + pMainThread->threadId, idealCoreCpuSetId, settings.idealCore); + pMainThread->hasCpuSets = true; + pMainThread->assignedCpuSetId = idealCoreCpuSetId; + } + CloseHandle(hMain); } } } From b19afb7d6542a1798e1a2f9e495432b636e90a93 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:24:19 +0800 Subject: [PATCH 06/23] Add files via upload --- ForegroundBooster.cpp | 195 +++++++++++++++++++++++++++--------------- 1 file changed, 124 insertions(+), 71 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 0bad481..b175fa5 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -49,6 +49,9 @@ struct ProcessStats { DWORD processId; std::map threads; bool isInitialized; + // --- 新增 --- + bool ignoreMonitoring; // 标记是否因自定义亲和性而停止监控 + // ----------- }; // 核心缓存:PID -> 进程统计数据 @@ -749,7 +752,7 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation ULONG returnLength = 0; // 第一次调用获取所需缓冲区大小 pGetSystemCpuSetInformation(NULL, 0, &returnLength, GetCurrentProcess(), 0); - + if (returnLength == 0) return 0; std::vector buffer(returnLength); @@ -766,7 +769,7 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation while (ptr < end) { PSYSTEM_CPU_SET_INFORMATION entry = (PSYSTEM_CPU_SET_INFORMATION)ptr; - + // Type 0 是 CpuSetInformation if (entry->Type == 0) { // CpuSetInformation if (entry->CpuSet.LogicalProcessorIndex == logicalIndex) { @@ -782,41 +785,44 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation return 0; // 未找到 } +// --- 新增:底层线程信息定义 (用于获取线程亲和性) --- +typedef struct _THREAD_BASIC_INFORMATION { + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + ULONG_PTR AffinityMask; + LONG Priority; + LONG BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; + +using NtQueryInformationThreadPtr = NTSTATUS(NTAPI*)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); + void ThreadOptimizerThread() { HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); - SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = + HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); + + SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); - GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = + GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); + NtQueryInformationThreadPtr pNtQueryInformationThread = + (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),将仅使用 IdealProcessor。\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),优化功能受限。\n"); } - // --- 预先解析 IdealCore 对应的 CpuSetId --- - ULONG idealCoreCpuSetId = 0; // IdealCore 对应的 CPU Set ID - ULONG mainThreadFallbackCpuSetId = 0; // IdealCore - 2 对应的 CPU Set ID + ULONG idealCoreCpuSetId = 0; + ULONG mainThreadFallbackCpuSetId = 0; if (settings.idealCore >= 0 && pGetSystemCpuSetInformation) { idealCoreCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); - if (idealCoreCpuSetId != 0) { - LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d 映射为 CPU Set ID: %lu\n", settings.idealCore, idealCoreCpuSetId); - } else { - LogColor(COLOR_ERROR, "[CPU Sets] 错误: 无法找到逻辑核心 %d 的 CPU Set ID。\n", settings.idealCore); - } - - if (settings.idealCore >= 2) { // 确保 IdealCore - 2 是有效核心 + if (settings.idealCore >= 2) { mainThreadFallbackCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)(settings.idealCore - 2), pGetSystemCpuSetInformation); - if (mainThreadFallbackCpuSetId != 0) { - LogColor(COLOR_INFO, "[CPU Sets] 逻辑核心 %d (IdealCore-2) 映射为 CPU Set ID: %lu\n", settings.idealCore - 2, mainThreadFallbackCpuSetId); - } else { - LogColor(COLOR_ERROR, "[CPU Sets] 错误: 无法找到逻辑核心 %d (IdealCore-2) 的 CPU Set ID。\n", settings.idealCore - 2); - } } } - // ------------------------------------------- while (true) { @@ -825,6 +831,49 @@ void ThreadOptimizerThread() DWORD currentPid = lastProcessId; if (currentPid == 0) continue; + // --- 1. 快速检查:是否已标记为忽略 --- + { + std::lock_guard lock(g_statsMutex); + // 如果缓存中存在该进程且标记为忽略,直接跳过本次循环 + if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) + { + continue; + } + } + + // --- 2. 亲和性检查 (在快照前执行,节省资源) --- + bool customAffinityDetected = false; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, currentPid); + if (hProcess) + { + DWORD_PTR processAffinity, systemAffinity; + if (GetProcessAffinityMask(hProcess, &processAffinity, &systemAffinity)) + { + if (processAffinity != systemAffinity) + { + customAffinityDetected = true; + } + } + CloseHandle(hProcess); + } + + // 如果检测到自定义亲和性,更新缓存状态并停止监控 + if (customAffinityDetected) + { + std::lock_guard lock(g_statsMutex); + ProcessStats& procStats = g_processStatsCache[currentPid]; + procStats.processId = currentPid; + + if (!procStats.ignoreMonitoring) // 仅在状态变更时执行 + { + procStats.ignoreMonitoring = true; + procStats.threads.clear(); // 清空线程数据,不再需要了 + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性,停止追踪其线程负载。\n", currentPid); + } + continue; // 跳过后续逻辑 + } + + // --- 3. 正常监控流程 (快照与计算) --- FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); @@ -858,7 +907,7 @@ void ThreadOptimizerThread() ThreadStats ts = {}; ts.threadId = tid; ts.smoothedLoad = 0.0; - ts.hasCpuSets = false; // 初始化为未设置 + ts.hasCpuSets = false; ts.assignedCpuSetId = 0; FILETIME ftExit, ftKernel, ftUser; if (GetThreadTimes(hThread, &ts.creationTime, &ftExit, &ftKernel, &ftUser)) @@ -882,9 +931,9 @@ void ThreadOptimizerThread() { ULARGE_INTEGER k = FT2ULL(ftKernel); ULARGE_INTEGER u = FT2ULL(ftUser); - + ULONGLONG timeDelta = now.QuadPart - ts.lastCheckTime.QuadPart; - ULONGLONG workDelta = (k.QuadPart - ts.lastKernelTime.QuadPart) + + ULONGLONG workDelta = (k.QuadPart - ts.lastKernelTime.QuadPart) + (u.QuadPart - ts.lastUserTime.QuadPart); if (timeDelta > 0) @@ -911,23 +960,15 @@ void ThreadOptimizerThread() for (DWORD activeTid : currentThreadIds) { if (activeTid == it->first) { exists = true; break; } } - if (!exists) { - // 如果线程退出,确保其 CPU Sets 状态被清除 - if (it->second.hasCpuSets) { - LogColor(COLOR_DEFAULT, " -> [优化] 线程 %lu 已退出,其 CPU Sets 状态已清除。\n", it->first); - } - it = procStats.threads.erase(it); - } - else { - ++it; - } + if (!exists) it = procStats.threads.erase(it); + else ++it; } // --- 分析与应用策略 --- if (!procStats.threads.empty()) { ThreadStats* pMainThread = nullptr; - ThreadStats* pHeavyThread = nullptr; // 负载最重的非主线程 + ThreadStats* pHeavyThread = nullptr; for (auto& pair : procStats.threads) { @@ -935,12 +976,11 @@ void ThreadOptimizerThread() if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) pMainThread = &t; } - - // 再次遍历,寻找最重负载的非主线程 + for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; - if (pMainThread && t.threadId != pMainThread->threadId) // 排除主线程 + if (pMainThread && t.threadId != pMainThread->threadId) { if (pHeavyThread == nullptr || t.smoothedLoad > pHeavyThread->smoothedLoad) pHeavyThread = &t; @@ -949,39 +989,53 @@ void ThreadOptimizerThread() if (pMainThread) pMainThread->isMainThread = true; - // --- 执行优化策略 (仅当配置了 IdealCore 且 CPU Sets API 可用时) --- + // --- 辅助 Lambda: 确保核心在线程亲和性范围内 --- + auto EnsureCoreInAffinity = [&](HANDLE hThread, DWORD coreIndex) { + if (!pNtQueryInformationThread) return; + THREAD_BASIC_INFORMATION tbi; + if (NT_SUCCESS(pNtQueryInformationThread(hThread, (THREADINFOCLASS)0, &tbi, sizeof(tbi), NULL))) + { + if (!(tbi.AffinityMask & (1ULL << coreIndex))) + { + DWORD_PTR newMask = tbi.AffinityMask | (1ULL << coreIndex); + if (SetThreadAffinityMask(hThread, newMask)) + { + LogColor(COLOR_INFO, " -> [亲和性修正] 将核心 %d 添加到线程亲和性掩码。\n", coreIndex); + } + } + } + }; + + // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { - // 1. 处理最重负载线程 (pHeavyThread) - if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) // 只有负载显著时才处理 + // 策略 A: 存在重负载辅助线程 + if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) { - // 如果最重负载线程不是 IdealCoreCpuSetId,或者之前分配了其他 ID,则重新设置 + // 1. 设置重负载线程 -> IdealCore if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { - // 清空之前设置了 CPU Sets 的其他线程 (除了主线程) + // 清理其他线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { HANDLE hOther = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, t.threadId); if (hOther) { - pSetThreadSelectedCpuSets(hOther, NULL, 0); // 清空 CPU Sets - LogColor(COLOR_DEFAULT, " -> [优化] 清空线程 %lu 的 CPU Sets (原分配: %lu)。\n", t.threadId, t.assignedCpuSetId); - t.hasCpuSets = false; - t.assignedCpuSetId = 0; + pSetThreadSelectedCpuSets(hOther, NULL, 0); + t.hasCpuSets = false; t.assignedCpuSetId = 0; CloseHandle(hOther); } } } - // 为当前最重负载线程设置 CPU Sets - HANDLE hHeavy = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pHeavyThread->threadId); + HANDLE hHeavy = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION, FALSE, pHeavyThread->threadId); if (hHeavy) { + EnsureCoreInAffinity(hHeavy, settings.idealCore); ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (最重负载) 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", - pHeavyThread->threadId, idealCoreCpuSetId, settings.idealCore); + LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu。\n", pHeavyThread->threadId, idealCoreCpuSetId); pHeavyThread->hasCpuSets = true; pHeavyThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -989,17 +1043,17 @@ void ThreadOptimizerThread() } } - // 2. 处理主线程 (如果最重负载线程不是主线程) - // 将主线程的 CPU Sets 设置为 IdealCore - 2 - if (pMainThread->assignedCpuSetId != mainThreadFallbackCpuSetId && mainThreadFallbackCpuSetId != 0) + // 2. 设置主线程 -> IdealCore - 2 + if (mainThreadFallbackCpuSetId != 0 && pMainThread->assignedCpuSetId != mainThreadFallbackCpuSetId) { - HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pMainThread->threadId); + HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION, FALSE, pMainThread->threadId); if (hMain) { + EnsureCoreInAffinity(hMain, settings.idealCore - 2); ULONG cpuSetIds[] = { mainThreadFallbackCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)。\n", pMainThread->threadId, mainThreadFallbackCpuSetId, settings.idealCore - 2); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = mainThreadFallbackCpuSetId; @@ -1008,34 +1062,33 @@ void ThreadOptimizerThread() } } } - else // 如果没有显著的重负载非主线程,或者重负载线程就是主线程 + // 策略 B: 无重负载辅助线程 + else { - // 清空所有非主线程的 CPU Sets + // 清理辅助线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { HANDLE hOther = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, t.threadId); if (hOther) { - pSetThreadSelectedCpuSets(hOther, NULL, 0); // 清空 CPU Sets - LogColor(COLOR_DEFAULT, " -> [优化] 清空线程 %lu 的 CPU Sets (原分配: %lu)。\n", t.threadId, t.assignedCpuSetId); - t.hasCpuSets = false; - t.assignedCpuSetId = 0; + pSetThreadSelectedCpuSets(hOther, NULL, 0); + t.hasCpuSets = false; t.assignedCpuSetId = 0; CloseHandle(hOther); } } } - // 将主线程的 CPU Sets 设置为 IdealCore + // 设置主线程 -> IdealCore if (!pMainThread->hasCpuSets || pMainThread->assignedCpuSetId != idealCoreCpuSetId) { - HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, pMainThread->threadId); + HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION, FALSE, pMainThread->threadId); if (hMain) { + EnsureCoreInAffinity(hMain, settings.idealCore); ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 已绑定 CPU Set ID: %lu (逻辑核: %d)。\n", - pMainThread->threadId, idealCoreCpuSetId, settings.idealCore); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu。\n", pMainThread->threadId, idealCoreCpuSetId); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1045,8 +1098,8 @@ void ThreadOptimizerThread() } } } - } - + } + CloseHandle(hSnapshot); } } @@ -1056,7 +1109,7 @@ void ProcessListCheckThread() while (true) { std::this_thread::sleep_for(std::chrono::seconds(settings.processListInterval)); - + // 检查前台是否发生变化 if (g_foregroundHasChanged.exchange(false)) { @@ -1150,11 +1203,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine std::thread t2(DwmThread); std::thread t3(ProcessListCheckThread); std::thread t4(ThreadOptimizerThread); // 新增的线程 - + t1.join(); t2.join(); t3.join(); t4.join(); // 等待新线程 - + return 0; } \ No newline at end of file From fe921c935174a31b7ba5cd9525680e7e87d6a530 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 22:26:48 +0800 Subject: [PATCH 07/23] Add files via upload --- ForegroundBooster.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index b175fa5..9f77089 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -785,7 +785,54 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation return 0; // 未找到 } -// --- 新增:底层线程信息定义 (用于获取线程亲和性) --- +// --- 补充 NTAPI 缺失的定义 --- + +// 1. 定义 CLIENT_ID +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID; + +// 2. 定义 THREADINFOCLASS 枚举 +typedef enum _THREADINFOCLASS { + ThreadBasicInformation = 0, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + ThreadSwitchLegacyState, + ThreadIsTerminated, + ThreadLastSystemCall, + ThreadIoPriority, + ThreadCycleTime, + ThreadPagePriority, + ThreadActualBasePriority, + ThreadTebInformation, + ThreadCSwitchMon, + ThreadCSwitchPmu, + ThreadWow64Context, + ThreadGroupInformation, + ThreadUmsInformation, + ThreadCounterProfiling, + ThreadIdealProcessorEx, + MaxThreadInfoClass +} THREADINFOCLASS; + +// 3. 定义 THREAD_BASIC_INFORMATION (现在 CLIENT_ID 已定义,不会报错了) typedef struct _THREAD_BASIC_INFORMATION { NTSTATUS ExitStatus; PVOID TebBaseAddress; @@ -795,6 +842,7 @@ typedef struct _THREAD_BASIC_INFORMATION { LONG BasePriority; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; +// 4. 定义函数指针 (现在 THREADINFOCLASS 已定义,不会报错了) using NtQueryInformationThreadPtr = NTSTATUS(NTAPI*)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); void ThreadOptimizerThread() From 84198de016a3afbfb536b0d5b0f5e1ed212bc515 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:14:37 +0800 Subject: [PATCH 08/23] Add files via upload --- ForegroundBooster.cpp | 270 +++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 134 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 9f77089..bea3e6d 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -33,24 +33,31 @@ std::mutex g_statsMutex; // 保护缓存的互斥锁 struct ThreadStats { DWORD threadId; FILETIME creationTime; + + // 用于每秒更新的瞬时数据 (保留用于调试或备用) ULARGE_INTEGER lastKernelTime; ULARGE_INTEGER lastUserTime; ULARGE_INTEGER lastCheckTime; - double currentLoad; // 当前瞬时负载 (0.0 - 100.0) - double smoothedLoad; // 平滑后的负载 (EMA算法) + + // --- 新增:用于长周期计算的快照数据 --- + ULARGE_INTEGER intervalStartKernelTime; + ULARGE_INTEGER intervalStartUserTime; + ULARGE_INTEGER intervalStartTime; + double intervalAverageLoad; // 周期内的平均负载 + // ------------------------------------ + bool isMainThread; - // --- 新增部分开始 --- - bool hasCpuSets; // 标记此线程是否被设置了 CPU Sets - ULONG assignedCpuSetId; // 如果设置了,记录分配的 CPU Set ID - // --- 新增部分结束 --- + bool hasCpuSets; + ULONG assignedCpuSetId; }; struct ProcessStats { DWORD processId; std::map threads; bool isInitialized; + bool ignoreMonitoring; // --- 新增 --- - bool ignoreMonitoring; // 标记是否因自定义亲和性而停止监控 + ULARGE_INTEGER lastOptimizationTime; // 上次执行 CPU Sets 设置的时间 // ----------- }; @@ -101,6 +108,9 @@ struct Settings int weight = -1; int processListInterval = 60; int idealCore = -1; + // --- 新增 --- + int cpuSetInterval = 600; // 默认 600 秒 (10分钟) + // ----------- }; Settings settings; std::set blackList, whiteList, blackListJob; @@ -109,10 +119,6 @@ std::map originalIoPriorities; DWORD lastProcessId = 0; DWORD lastAttachedThreadId = 0; -// 用于缓存已处理或已跳过的进程 避免重复操作 -std::set> idealCoreSetCache; -std::set> idealCoreSkippedCache; - // --- 后台进程扫描缓存 --- struct ProcessInfo { @@ -254,6 +260,7 @@ void ParseIniFile(const std::wstring& path) else if (key == L"Weight") settings.weight = std::stoi(value); else if (key == L"ProcessList") settings.processListInterval = std::stoi(value); else if (key == L"IdealCore") settings.idealCore = std::stoi(value); + else if (key == L"CpuSetInterval") settings.cpuSetInterval = std::stoi(value); } } else if (currentSection == L"BlackList") @@ -572,68 +579,6 @@ void CALLBACK ForegroundEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND LogColor(COLOR_WARNING, " -> 进程位于作业对象黑名单中 跳过Job Object操作\n"); } } - // --- 新增部分开始: 设置主线程理想核心 --- - if (settings.idealCore >= 0) - { - std::pair processKey = { processNameLower, currentProcessId }; - - if (idealCoreSetCache.count(processKey)) - { - LogColor(COLOR_INFO, " -> 理想核心: 进程已在成功缓存中 跳过\n"); - } - else if (idealCoreSkippedCache.count(processKey)) - { - LogColor(COLOR_INFO, " -> 理想核心: 进程已在跳过缓存中 跳过\n"); - } - else - { - LogColor(COLOR_INFO, " -> 正在尝试为进程主线程设置理想核心...\n"); - DWORD_PTR processAffinity, systemAffinity; - if (GetProcessAffinityMask(hNewProcess, &processAffinity, &systemAffinity)) - { - // 检查是否设置了自定义亲和性 (如果进程亲和性与系统总亲和性不同) - // 并且理想核心不在亲和性掩码内 - if (processAffinity != systemAffinity && (processAffinity & (1ULL << settings.idealCore)) == 0) - { - LogColor(COLOR_WARNING, " - 跳过: 理想核心 %d 不在亲和性 (%llu) 范围内\n", settings.idealCore, processAffinity); - idealCoreSkippedCache.insert(processKey); - } - else - { - DWORD mainThreadId = GetProcessMainThreadId(currentProcessId); - if (mainThreadId != 0) - { - HANDLE hMainThread = OpenThread(THREAD_SET_INFORMATION, FALSE, mainThreadId); - if (hMainThread) - { - if (SetThreadIdealProcessor(hMainThread, settings.idealCore) != (DWORD)-1) - { - LogColor(COLOR_SUCCESS, " - 成功: 已将主线程 %lu 的理想核心设置为 %d\n", mainThreadId, settings.idealCore); - idealCoreSetCache.insert(processKey); - } - else - { - LogColor(COLOR_ERROR, " - 失败: 调用 SetThreadIdealProcessor 失败 错误码: %lu\n", GetLastError()); - } - CloseHandle(hMainThread); - } - else - { - LogColor(COLOR_ERROR, " - 失败: 无法打开主线程句柄 错误码: %lu\n", GetLastError()); - } - } - else - { - LogColor(COLOR_ERROR, " - 失败: 无法找到进程的主线程\n"); - } - } - } - else - { - LogColor(COLOR_ERROR, " - 失败: 无法获取进程亲和性掩码 错误码: %lu\n", GetLastError()); - } - } - } CloseHandle(hNewProcess); } else @@ -777,7 +722,7 @@ ULONG GetCpuSetIdFromLogicalIndex(DWORD logicalIndex, GetSystemCpuSetInformation } } - // 移动到下一个条目 (注意:必须使用 entry->Size,因为结构体大小可能随系统版本变化) + // 移动到下一个条目 (注意:必须使用 entry->Size 因为结构体大小可能随系统版本变化) if (entry->Size == 0) break; // 防止死循环 ptr += entry->Size; } @@ -832,7 +777,7 @@ typedef enum _THREADINFOCLASS { MaxThreadInfoClass } THREADINFOCLASS; -// 3. 定义 THREAD_BASIC_INFORMATION (现在 CLIENT_ID 已定义,不会报错了) +// 3. 定义 THREAD_BASIC_INFORMATION (现在 CLIENT_ID 已定义 不会报错了) typedef struct _THREAD_BASIC_INFORMATION { NTSTATUS ExitStatus; PVOID TebBaseAddress; @@ -842,7 +787,7 @@ typedef struct _THREAD_BASIC_INFORMATION { LONG BasePriority; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; -// 4. 定义函数指针 (现在 THREADINFOCLASS 已定义,不会报错了) +// 4. 定义函数指针 (现在 THREADINFOCLASS 已定义 不会报错了) using NtQueryInformationThreadPtr = NTSTATUS(NTAPI*)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); void ThreadOptimizerThread() @@ -859,7 +804,7 @@ void ThreadOptimizerThread() if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),优化功能受限。\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+) 优化功能受限\n"); } ULONG idealCoreCpuSetId = 0; @@ -872,24 +817,23 @@ void ThreadOptimizerThread() } } + DWORD previousPid = 0; // 用于检测前台进程切换 + while (true) { + // 1. 持续监控:每秒唤醒一次 收集数据 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; if (currentPid == 0) continue; - // --- 1. 快速检查:是否已标记为忽略 --- + // --- 快速检查:是否忽略 --- { std::lock_guard lock(g_statsMutex); - // 如果缓存中存在该进程且标记为忽略,直接跳过本次循环 - if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) - { - continue; - } + if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) continue; } - // --- 2. 亲和性检查 (在快照前执行,节省资源) --- + // --- 2. 亲和性检查 (在快照前执行 节省资源) --- bool customAffinityDetected = false; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, currentPid); if (hProcess) @@ -905,7 +849,7 @@ void ThreadOptimizerThread() CloseHandle(hProcess); } - // 如果检测到自定义亲和性,更新缓存状态并停止监控 + // 如果检测到自定义亲和性 更新缓存状态并停止监控 if (customAffinityDetected) { std::lock_guard lock(g_statsMutex); @@ -915,8 +859,8 @@ void ThreadOptimizerThread() if (!procStats.ignoreMonitoring) // 仅在状态变更时执行 { procStats.ignoreMonitoring = true; - procStats.threads.clear(); // 清空线程数据,不再需要了 - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性,停止追踪其线程负载。\n", currentPid); + procStats.threads.clear(); // 清空线程数据 不再需要了 + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性 停止追踪其线程负载\n", currentPid); } continue; // 跳过后续逻辑 } @@ -938,6 +882,21 @@ void ThreadOptimizerThread() ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; + // --- 关键逻辑:检测前台切换 --- + // 如果刚切换到这个进程 重置计时器 开始新的观察周期 + if (currentPid != previousPid) + { + LogColor(COLOR_INFO, "[监控] 开始监控进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); + procStats.lastOptimizationTime = now; + // 重置所有线程的快照 + for (auto& pair : procStats.threads) { + pair.second.intervalStartTime = now; // 强制重置时间 稍后会更新 Kernel/User Time + // 这里只是标记 具体数值会在下面 OpenThread 时更新 + } + previousPid = currentPid; + } + + // --- 更新线程列表与快照 --- if (Thread32First(hSnapshot, &te32)) { do @@ -947,54 +906,49 @@ void ThreadOptimizerThread() DWORD tid = te32.th32ThreadID; currentThreadIds.push_back(tid); - if (procStats.threads.find(tid) == procStats.threads.end()) + // 如果是新线程 或者刚切换过来需要重置快照 + bool isNewThread = (procStats.threads.find(tid) == procStats.threads.end()); + + if (isNewThread) { + ThreadStats ts = {}; + ts.threadId = tid; + ts.hasCpuSets = false; + ts.assignedCpuSetId = 0; + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); if (hThread) { - ThreadStats ts = {}; - ts.threadId = tid; - ts.smoothedLoad = 0.0; - ts.hasCpuSets = false; - ts.assignedCpuSetId = 0; FILETIME ftExit, ftKernel, ftUser; if (GetThreadTimes(hThread, &ts.creationTime, &ftExit, &ftKernel, &ftUser)) { - ts.lastKernelTime = FT2ULL(ftKernel); - ts.lastUserTime = FT2ULL(ftUser); - ts.lastCheckTime = now; - procStats.threads[tid] = ts; + // 初始化快照数据 + ts.intervalStartKernelTime = FT2ULL(ftKernel); + ts.intervalStartUserTime = FT2ULL(ftUser); + ts.intervalStartTime = now; } CloseHandle(hThread); } + procStats.threads[tid] = ts; } else { + // 如果是已存在的线程 且 intervalStartTime 与当前周期不匹配(例如刚切换过来) 则更新快照 ThreadStats& ts = procStats.threads[tid]; - HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); - if (hThread) + if (ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) { - FILETIME ftCreation, ftExit, ftKernel, ftUser; - if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); + if (hThread) { - ULARGE_INTEGER k = FT2ULL(ftKernel); - ULARGE_INTEGER u = FT2ULL(ftUser); - - ULONGLONG timeDelta = now.QuadPart - ts.lastCheckTime.QuadPart; - ULONGLONG workDelta = (k.QuadPart - ts.lastKernelTime.QuadPart) + - (u.QuadPart - ts.lastUserTime.QuadPart); - - if (timeDelta > 0) + FILETIME ftCreation, ftExit, ftKernel, ftUser; + if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) { - ts.currentLoad = (double)workDelta / (double)timeDelta * 100.0; - ts.smoothedLoad = 0.3 * ts.currentLoad + 0.7 * ts.smoothedLoad; + ts.intervalStartKernelTime = FT2ULL(ftKernel); + ts.intervalStartUserTime = FT2ULL(ftUser); + ts.intervalStartTime = now; // 同步到当前周期开始时间 } - - ts.lastKernelTime = k; - ts.lastUserTime = u; - ts.lastCheckTime = now; + CloseHandle(hThread); } - CloseHandle(hThread); } } } @@ -1012,9 +966,54 @@ void ThreadOptimizerThread() else ++it; } - // --- 分析与应用策略 --- - if (!procStats.threads.empty()) + // --- 检查是否达到优化间隔 --- + ULONGLONG timeSinceLastOpt = now.QuadPart - procStats.lastOptimizationTime.QuadPart; + // FileTime 单位是 100纳秒 1秒 = 10,000,000 单位 + ULONGLONG intervalUnits = (ULONGLONG)settings.cpuSetInterval * 10000000ULL; + + if (timeSinceLastOpt >= intervalUnits) { + LogColor(COLOR_INFO, "[分析] 观察周期 (%d秒) 结束 正在计算平均负载并应用优化...\n", settings.cpuSetInterval); + + // 1. 计算周期内的平均负载 + for (auto& pair : procStats.threads) + { + ThreadStats& ts = pair.second; + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, ts.threadId); + if (hThread) + { + FILETIME ftCreation, ftExit, ftKernel, ftUser; + if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) + { + ULARGE_INTEGER k = FT2ULL(ftKernel); + ULARGE_INTEGER u = FT2ULL(ftUser); + + ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; + ULONGLONG workDelta = (k.QuadPart - ts.intervalStartKernelTime.QuadPart) + + (u.QuadPart - ts.intervalStartUserTime.QuadPart); + + if (timeDelta > 0) + { + ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; + } + else + { + ts.intervalAverageLoad = 0.0; + } + + // 重置快照 为下一个周期做准备 + ts.intervalStartKernelTime = k; + ts.intervalStartUserTime = u; + ts.intervalStartTime = now; + } + CloseHandle(hThread); + } + } + + // 更新上次优化时间 + procStats.lastOptimizationTime = now; + + // 2. 识别主线程和重负载线程 (使用 intervalAverageLoad) ThreadStats* pMainThread = nullptr; ThreadStats* pHeavyThread = nullptr; @@ -1030,14 +1029,15 @@ void ThreadOptimizerThread() ThreadStats& t = pair.second; if (pMainThread && t.threadId != pMainThread->threadId) { - if (pHeavyThread == nullptr || t.smoothedLoad > pHeavyThread->smoothedLoad) + // 使用平均负载判断 + if (pHeavyThread == nullptr || t.intervalAverageLoad > pHeavyThread->intervalAverageLoad) pHeavyThread = &t; } } if (pMainThread) pMainThread->isMainThread = true; - // --- 辅助 Lambda: 确保核心在线程亲和性范围内 --- + // --- 辅助 Lambda (保持不变) --- auto EnsureCoreInAffinity = [&](HANDLE hThread, DWORD coreIndex) { if (!pNtQueryInformationThread) return; THREAD_BASIC_INFORMATION tbi; @@ -1046,20 +1046,21 @@ void ThreadOptimizerThread() if (!(tbi.AffinityMask & (1ULL << coreIndex))) { DWORD_PTR newMask = tbi.AffinityMask | (1ULL << coreIndex); - if (SetThreadAffinityMask(hThread, newMask)) - { - LogColor(COLOR_INFO, " -> [亲和性修正] 将核心 %d 添加到线程亲和性掩码。\n", coreIndex); - } + SetThreadAffinityMask(hThread, newMask); } } }; - // --- 执行优化策略 --- + // --- 执行优化策略 (保持不变 但使用 intervalAverageLoad 判断) --- if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { - // 策略 A: 存在重负载辅助线程 - if (pHeavyThread && pHeavyThread->smoothedLoad > 10.0) + // 策略 A: 存在重负载辅助线程 (平均负载 > 10%) + if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { + LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", + pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); + + // ... (此处保留原有的 CPU Sets 设置代码 完全一致) ... // 1. 设置重负载线程 -> IdealCore if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { @@ -1083,7 +1084,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu。\n", pHeavyThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu\n", pHeavyThread->threadId, idealCoreCpuSetId); pHeavyThread->hasCpuSets = true; pHeavyThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1101,7 +1102,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { mainThreadFallbackCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)。\n", + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)\n", pMainThread->threadId, mainThreadFallbackCpuSetId, settings.idealCore - 2); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = mainThreadFallbackCpuSetId; @@ -1113,7 +1114,8 @@ void ThreadOptimizerThread() // 策略 B: 无重负载辅助线程 else { - // 清理辅助线程 + // ... (此处保留原有的 CPU Sets 设置代码 完全一致) ... + // 清理辅助线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { @@ -1136,7 +1138,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu。\n", pMainThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu\n", pMainThread->threadId, idealCoreCpuSetId); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1161,7 +1163,7 @@ void ProcessListCheckThread() // 检查前台是否发生变化 if (g_foregroundHasChanged.exchange(false)) { - LogColor(COLOR_INFO, "[状态变更] 前台进程已切换,正在执行维护任务...\n"); + LogColor(COLOR_INFO, "[状态变更] 前台进程已切换 正在执行维护任务...\n"); // --- 1. 清理已退出进程的缓存数据 (仅在此处执行) --- { @@ -1182,12 +1184,12 @@ void ProcessListCheckThread() CloseHandle(hSnapshot); } - // 遍历缓存,移除不在 runningPids 中的进程 + // 遍历缓存 移除不在 runningPids 中的进程 for (auto it = g_processStatsCache.begin(); it != g_processStatsCache.end(); ) { if (runningPids.find(it->first) == runningPids.end()) { - LogColor(COLOR_DEFAULT, " -> [缓存清理] 进程 PID %lu 已退出,清除其线程负载数据。\n", it->first); + LogColor(COLOR_DEFAULT, " -> [缓存清理] 进程 PID %lu 已退出 清除其线程负载数据\n", it->first); it = g_processStatsCache.erase(it); } else From 81b6159d649b894f65def543115201b75dc6adb5 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Thu, 25 Dec 2025 23:26:09 +0800 Subject: [PATCH 09/23] Add files via upload --- ForegroundBooster.cpp | 168 ++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 78 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index bea3e6d..dfab6ea 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -817,11 +817,10 @@ void ThreadOptimizerThread() } } - DWORD previousPid = 0; // 用于检测前台进程切换 + DWORD previousPid = 0; while (true) { - // 1. 持续监控:每秒唤醒一次 收集数据 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; @@ -833,7 +832,7 @@ void ThreadOptimizerThread() if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) continue; } - // --- 2. 亲和性检查 (在快照前执行 节省资源) --- + // --- 亲和性检查 --- bool customAffinityDetected = false; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, currentPid); if (hProcess) @@ -841,31 +840,25 @@ void ThreadOptimizerThread() DWORD_PTR processAffinity, systemAffinity; if (GetProcessAffinityMask(hProcess, &processAffinity, &systemAffinity)) { - if (processAffinity != systemAffinity) - { - customAffinityDetected = true; - } + if (processAffinity != systemAffinity) customAffinityDetected = true; } CloseHandle(hProcess); } - // 如果检测到自定义亲和性 更新缓存状态并停止监控 if (customAffinityDetected) { std::lock_guard lock(g_statsMutex); ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; - - if (!procStats.ignoreMonitoring) // 仅在状态变更时执行 + if (!procStats.ignoreMonitoring) { procStats.ignoreMonitoring = true; - procStats.threads.clear(); // 清空线程数据 不再需要了 - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性 停止追踪其线程负载\n", currentPid); + procStats.threads.clear(); + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置亲和性 停止追踪其线程负载\n", currentPid); } - continue; // 跳过后续逻辑 + continue; } - // --- 3. 正常监控流程 (快照与计算) --- FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); @@ -883,15 +876,27 @@ void ThreadOptimizerThread() procStats.processId = currentPid; // --- 关键逻辑:检测前台切换 --- - // 如果刚切换到这个进程 重置计时器 开始新的观察周期 if (currentPid != previousPid) { - LogColor(COLOR_INFO, "[监控] 开始监控进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); - procStats.lastOptimizationTime = now; - // 重置所有线程的快照 - for (auto& pair : procStats.threads) { - pair.second.intervalStartTime = now; // 强制重置时间 稍后会更新 Kernel/User Time - // 这里只是标记 具体数值会在下面 OpenThread 时更新 + // 检查是否为新进程 (lastOptimizationTime 为 0 表示从未优化过) + if (procStats.lastOptimizationTime.QuadPart == 0) + { + LogColor(COLOR_INFO, "[监控] 新进程 %lu 立即执行首次优化\n", currentPid); + // 注意:这里不重置 lastOptimizationTime 保持为 0 + // 这样下面的 (now - 0 > interval) 判断会成立 触发立即执行 + } + else + { + LogColor(COLOR_INFO, "[监控] 旧进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); + procStats.lastOptimizationTime = now; // 重置计时器 强制等待完整周期 + + // 重置现有线程的快照 开始新的观察周期 + for (auto& pair : procStats.threads) { + pair.second.intervalStartTime = now; + // 同步内核/用户时间基准 避免计算出错误的巨大负载 + pair.second.intervalStartKernelTime = pair.second.lastKernelTime; + pair.second.intervalStartUserTime = pair.second.lastUserTime; + } } previousPid = currentPid; } @@ -906,7 +911,6 @@ void ThreadOptimizerThread() DWORD tid = te32.th32ThreadID; currentThreadIds.push_back(tid); - // 如果是新线程 或者刚切换过来需要重置快照 bool isNewThread = (procStats.threads.find(tid) == procStats.threads.end()); if (isNewThread) @@ -922,9 +926,13 @@ void ThreadOptimizerThread() FILETIME ftExit, ftKernel, ftUser; if (GetThreadTimes(hThread, &ts.creationTime, &ftExit, &ftKernel, &ftUser)) { - // 初始化快照数据 - ts.intervalStartKernelTime = FT2ULL(ftKernel); - ts.intervalStartUserTime = FT2ULL(ftUser); + ts.lastKernelTime = FT2ULL(ftKernel); + ts.lastUserTime = FT2ULL(ftUser); + ts.lastCheckTime = now; + + // 初始化周期快照 + ts.intervalStartKernelTime = ts.lastKernelTime; + ts.intervalStartUserTime = ts.lastUserTime; ts.intervalStartTime = now; } CloseHandle(hThread); @@ -933,22 +941,29 @@ void ThreadOptimizerThread() } else { - // 如果是已存在的线程 且 intervalStartTime 与当前周期不匹配(例如刚切换过来) 则更新快照 + // 维护现有线程的瞬时数据 (lastKernelTime 等) ThreadStats& ts = procStats.threads[tid]; - if (ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); + if (hThread) { - HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); - if (hThread) + FILETIME ftCreation, ftExit, ftKernel, ftUser; + if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) { - FILETIME ftCreation, ftExit, ftKernel, ftUser; - if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) + ts.lastKernelTime = FT2ULL(ftKernel); + ts.lastUserTime = FT2ULL(ftUser); + ts.lastCheckTime = now; + + // 如果该线程的周期开始时间与当前周期不符 (例如旧进程切换回来后的首次循环) + // 且不是因为"新进程立即执行"导致的差异 + if (procStats.lastOptimizationTime.QuadPart != 0 && + ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) { - ts.intervalStartKernelTime = FT2ULL(ftKernel); - ts.intervalStartUserTime = FT2ULL(ftUser); - ts.intervalStartTime = now; // 同步到当前周期开始时间 + ts.intervalStartKernelTime = ts.lastKernelTime; + ts.intervalStartUserTime = ts.lastUserTime; + ts.intervalStartTime = now; } - CloseHandle(hThread); } + CloseHandle(hThread); } } } @@ -968,52 +983,48 @@ void ThreadOptimizerThread() // --- 检查是否达到优化间隔 --- ULONGLONG timeSinceLastOpt = now.QuadPart - procStats.lastOptimizationTime.QuadPart; - // FileTime 单位是 100纳秒 1秒 = 10,000,000 单位 ULONGLONG intervalUnits = (ULONGLONG)settings.cpuSetInterval * 10000000ULL; + // 如果是新进程(lastOpt=0) timeSinceLastOpt 会非常大 必然 > intervalUnits 触发立即执行 if (timeSinceLastOpt >= intervalUnits) { - LogColor(COLOR_INFO, "[分析] 观察周期 (%d秒) 结束 正在计算平均负载并应用优化...\n", settings.cpuSetInterval); + bool isImmediateRun = (procStats.lastOptimizationTime.QuadPart == 0); + if (isImmediateRun) { + LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); + } else { + LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); + } // 1. 计算周期内的平均负载 for (auto& pair : procStats.threads) { ThreadStats& ts = pair.second; - HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, ts.threadId); - if (hThread) - { - FILETIME ftCreation, ftExit, ftKernel, ftUser; - if (GetThreadTimes(hThread, &ftCreation, &ftExit, &ftKernel, &ftUser)) - { - ULARGE_INTEGER k = FT2ULL(ftKernel); - ULARGE_INTEGER u = FT2ULL(ftUser); + // 如果是立即执行 时间差几乎为0 负载设为0 + if (isImmediateRun) { + ts.intervalAverageLoad = 0.0; + continue; + } - ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; - ULONGLONG workDelta = (k.QuadPart - ts.intervalStartKernelTime.QuadPart) + - (u.QuadPart - ts.intervalStartUserTime.QuadPart); + // 正常计算 + ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; + ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + + (ts.lastUserTime.QuadPart - ts.intervalStartUserTime.QuadPart); - if (timeDelta > 0) - { - ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; - } - else - { - ts.intervalAverageLoad = 0.0; - } + if (timeDelta > 0) + ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; + else + ts.intervalAverageLoad = 0.0; - // 重置快照 为下一个周期做准备 - ts.intervalStartKernelTime = k; - ts.intervalStartUserTime = u; - ts.intervalStartTime = now; - } - CloseHandle(hThread); - } + // 重置快照 + ts.intervalStartKernelTime = ts.lastKernelTime; + ts.intervalStartUserTime = ts.lastUserTime; + ts.intervalStartTime = now; } - // 更新上次优化时间 + // 更新上次优化时间 (这会结束"新进程"状态) procStats.lastOptimizationTime = now; - // 2. 识别主线程和重负载线程 (使用 intervalAverageLoad) + // 2. 识别主线程和重负载线程 ThreadStats* pMainThread = nullptr; ThreadStats* pHeavyThread = nullptr; @@ -1024,20 +1035,23 @@ void ThreadOptimizerThread() pMainThread = &t; } - for (auto& pair : procStats.threads) + // 仅在非立即执行模式下查找重负载线程 + if (!isImmediateRun) { - ThreadStats& t = pair.second; - if (pMainThread && t.threadId != pMainThread->threadId) + for (auto& pair : procStats.threads) { - // 使用平均负载判断 - if (pHeavyThread == nullptr || t.intervalAverageLoad > pHeavyThread->intervalAverageLoad) - pHeavyThread = &t; + ThreadStats& t = pair.second; + if (pMainThread && t.threadId != pMainThread->threadId) + { + if (pHeavyThread == nullptr || t.intervalAverageLoad > pHeavyThread->intervalAverageLoad) + pHeavyThread = &t; + } } } if (pMainThread) pMainThread->isMainThread = true; - // --- 辅助 Lambda (保持不变) --- + // --- 辅助 Lambda --- auto EnsureCoreInAffinity = [&](HANDLE hThread, DWORD coreIndex) { if (!pNtQueryInformationThread) return; THREAD_BASIC_INFORMATION tbi; @@ -1051,16 +1065,15 @@ void ThreadOptimizerThread() } }; - // --- 执行优化策略 (保持不变 但使用 intervalAverageLoad 判断) --- + // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { - // 策略 A: 存在重负载辅助线程 (平均负载 > 10%) + // 策略 A: 存在重负载辅助线程 (且不是立即执行模式) if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); - // ... (此处保留原有的 CPU Sets 设置代码 完全一致) ... // 1. 设置重负载线程 -> IdealCore if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { @@ -1111,11 +1124,10 @@ void ThreadOptimizerThread() } } } - // 策略 B: 无重负载辅助线程 + // 策略 B: 无重负载辅助线程 (或立即执行模式) else { - // ... (此处保留原有的 CPU Sets 设置代码 完全一致) ... - // 清理辅助线程 + // 清理辅助线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { From b862756104e48e9179eb49c65d10bd63d32093a9 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:26:28 +0800 Subject: [PATCH 10/23] Add files via upload --- ForegroundBooster.cpp | 203 +++++++++++++++++++++++++++++++++++------- 1 file changed, 171 insertions(+), 32 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index dfab6ea..1ef47dc 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -108,8 +108,9 @@ struct Settings int weight = -1; int processListInterval = 60; int idealCore = -1; + int cpuSetInterval = 600; // --- 新增 --- - int cpuSetInterval = 600; // 默认 600 秒 (10分钟) + bool optimizeOtherThreads = false; // 是否优化其余线程 // ----------- }; Settings settings; @@ -261,6 +262,7 @@ void ParseIniFile(const std::wstring& path) else if (key == L"ProcessList") settings.processListInterval = std::stoi(value); else if (key == L"IdealCore") settings.idealCore = std::stoi(value); else if (key == L"CpuSetInterval") settings.cpuSetInterval = std::stoi(value); + else if (key == L"OptimizeOtherThreads") settings.optimizeOtherThreads = (std::stoi(value) != 0); } } else if (currentSection == L"BlackList") @@ -790,8 +792,78 @@ typedef struct _THREAD_BASIC_INFORMATION { // 4. 定义函数指针 (现在 THREADINFOCLASS 已定义 不会报错了) using NtQueryInformationThreadPtr = NTSTATUS(NTAPI*)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); +// --- 新增:CPU 拓扑分析结构 --- +struct CpuTopology { + std::vector pCores; // 性能核 (物理主核) + std::vector htCores; // 超线程 (逻辑核) + std::vector eCores; // 效率核 + std::map lpToCoreIndex; // 逻辑核 -> 物理核索引映射 + bool isInitialized = false; +}; + +// 辅助函数:分析系统拓扑 +void AnalyzeCpuTopology(GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation, CpuTopology& topology) { + if (!pGetSystemCpuSetInformation || topology.isInitialized) return; + + ULONG returnLength = 0; + pGetSystemCpuSetInformation(NULL, 0, &returnLength, GetCurrentProcess(), 0); + if (returnLength == 0) return; + + std::vector buffer(returnLength); + if (!pGetSystemCpuSetInformation((PSYSTEM_CPU_SET_INFORMATION)buffer.data(), returnLength, &returnLength, GetCurrentProcess(), 0)) return; + + std::map> coreGroups; // CoreIndex -> [LogicalProcessors] + std::map coreEfficiency; // CoreIndex -> EfficiencyClass + + BYTE* ptr = buffer.data(); + BYTE* end = ptr + returnLength; + + while (ptr < end) { + PSYSTEM_CPU_SET_INFORMATION entry = (PSYSTEM_CPU_SET_INFORMATION)ptr; + if (entry->Type == 0) { // CpuSetInformation + coreGroups[entry->CpuSet.CoreIndex].push_back(entry->CpuSet.LogicalProcessorIndex); + coreEfficiency[entry->CpuSet.CoreIndex] = entry->CpuSet.EfficiencyClass; + topology.lpToCoreIndex[entry->CpuSet.LogicalProcessorIndex] = entry->CpuSet.CoreIndex; + } + if (entry->Size == 0) break; + ptr += entry->Size; + } + + // 分类核心 + for (auto& pair : coreGroups) { + DWORD coreIndex = pair.first; + std::vector& lps = pair.second; + BYTE eff = coreEfficiency[coreIndex]; + + // 简单假设:EfficiencyClass 0 为 E核 >=1 为 P核 (适用于 Intel 12/13/14代) + // 如果所有核心 EfficiencyClass 都相同 则视为全 P核 + if (eff == 0 && coreEfficiency.size() > 1) { + // E-Cores + for (DWORD lp : lps) topology.eCores.push_back(lp); + } else { + // P-Cores & HT + std::sort(lps.begin(), lps.end()); + if (!lps.empty()) { + topology.pCores.push_back(lps[0]); // 第一个逻辑核视为物理主核 + for (size_t i = 1; i < lps.size(); ++i) { + topology.htCores.push_back(lps[i]); // 后续的视为超线程 + } + } + } + } + + // 排序以确保顺序确定性 + std::sort(topology.pCores.begin(), topology.pCores.end()); // 正序 + std::sort(topology.htCores.begin(), topology.htCores.end()); // 正序 (稍后使用时再倒序) + std::sort(topology.eCores.begin(), topology.eCores.end()); // 正序 + + topology.isInitialized = true; + LogColor(COLOR_INFO, "[拓扑] P核: %zu, HT: %zu, E核: %zu\n", topology.pCores.size(), topology.htCores.size(), topology.eCores.size()); +} + void ThreadOptimizerThread() { + // --- 加载 API --- HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); @@ -807,6 +879,7 @@ void ThreadOptimizerThread() LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+) 优化功能受限\n"); } + // --- 预先解析 IdealCore 对应的 CpuSetId --- ULONG idealCoreCpuSetId = 0; ULONG mainThreadFallbackCpuSetId = 0; @@ -817,10 +890,13 @@ void ThreadOptimizerThread() } } + // --- 初始化拓扑结构 --- + CpuTopology topology; DWORD previousPid = 0; while (true) { + // 1. 持续监控:每秒唤醒一次 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; @@ -859,6 +935,11 @@ void ThreadOptimizerThread() continue; } + // --- 初始化拓扑 (仅一次) --- + if (!topology.isInitialized && pGetSystemCpuSetInformation) { + AnalyzeCpuTopology(pGetSystemCpuSetInformation, topology); + } + FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); @@ -875,25 +956,21 @@ void ThreadOptimizerThread() ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; - // --- 关键逻辑:检测前台切换 --- + // --- 检测前台切换 --- if (currentPid != previousPid) { - // 检查是否为新进程 (lastOptimizationTime 为 0 表示从未优化过) if (procStats.lastOptimizationTime.QuadPart == 0) { LogColor(COLOR_INFO, "[监控] 新进程 %lu 立即执行首次优化\n", currentPid); - // 注意:这里不重置 lastOptimizationTime 保持为 0 - // 这样下面的 (now - 0 > interval) 判断会成立 触发立即执行 } else { LogColor(COLOR_INFO, "[监控] 旧进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); - procStats.lastOptimizationTime = now; // 重置计时器 强制等待完整周期 + procStats.lastOptimizationTime = now; // 重置计时器 - // 重置现有线程的快照 开始新的观察周期 + // 重置快照 for (auto& pair : procStats.threads) { pair.second.intervalStartTime = now; - // 同步内核/用户时间基准 避免计算出错误的巨大负载 pair.second.intervalStartKernelTime = pair.second.lastKernelTime; pair.second.intervalStartUserTime = pair.second.lastUserTime; } @@ -930,7 +1007,6 @@ void ThreadOptimizerThread() ts.lastUserTime = FT2ULL(ftUser); ts.lastCheckTime = now; - // 初始化周期快照 ts.intervalStartKernelTime = ts.lastKernelTime; ts.intervalStartUserTime = ts.lastUserTime; ts.intervalStartTime = now; @@ -941,7 +1017,6 @@ void ThreadOptimizerThread() } else { - // 维护现有线程的瞬时数据 (lastKernelTime 等) ThreadStats& ts = procStats.threads[tid]; HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); if (hThread) @@ -953,8 +1028,6 @@ void ThreadOptimizerThread() ts.lastUserTime = FT2ULL(ftUser); ts.lastCheckTime = now; - // 如果该线程的周期开始时间与当前周期不符 (例如旧进程切换回来后的首次循环) - // 且不是因为"新进程立即执行"导致的差异 if (procStats.lastOptimizationTime.QuadPart != 0 && ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) { @@ -985,46 +1058,36 @@ void ThreadOptimizerThread() ULONGLONG timeSinceLastOpt = now.QuadPart - procStats.lastOptimizationTime.QuadPart; ULONGLONG intervalUnits = (ULONGLONG)settings.cpuSetInterval * 10000000ULL; - // 如果是新进程(lastOpt=0) timeSinceLastOpt 会非常大 必然 > intervalUnits 触发立即执行 if (timeSinceLastOpt >= intervalUnits) { bool isImmediateRun = (procStats.lastOptimizationTime.QuadPart == 0); - if (isImmediateRun) { - LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); - } else { - LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); - } + if (isImmediateRun) LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); + else LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); - // 1. 计算周期内的平均负载 + // 1. 计算平均负载 for (auto& pair : procStats.threads) { ThreadStats& ts = pair.second; - // 如果是立即执行 时间差几乎为0 负载设为0 if (isImmediateRun) { ts.intervalAverageLoad = 0.0; continue; } - // 正常计算 ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + (ts.lastUserTime.QuadPart - ts.intervalStartUserTime.QuadPart); - if (timeDelta > 0) - ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; - else - ts.intervalAverageLoad = 0.0; + if (timeDelta > 0) ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; + else ts.intervalAverageLoad = 0.0; - // 重置快照 ts.intervalStartKernelTime = ts.lastKernelTime; ts.intervalStartUserTime = ts.lastUserTime; ts.intervalStartTime = now; } - // 更新上次优化时间 (这会结束"新进程"状态) procStats.lastOptimizationTime = now; - // 2. 识别主线程和重负载线程 + // 2. 识别线程 ThreadStats* pMainThread = nullptr; ThreadStats* pHeavyThread = nullptr; @@ -1035,7 +1098,6 @@ void ThreadOptimizerThread() pMainThread = &t; } - // 仅在非立即执行模式下查找重负载线程 if (!isImmediateRun) { for (auto& pair : procStats.threads) @@ -1051,7 +1113,7 @@ void ThreadOptimizerThread() if (pMainThread) pMainThread->isMainThread = true; - // --- 辅助 Lambda --- + // --- 辅助 Lambda: 亲和性修正 --- auto EnsureCoreInAffinity = [&](HANDLE hThread, DWORD coreIndex) { if (!pNtQueryInformationThread) return; THREAD_BASIC_INFORMATION tbi; @@ -1068,12 +1130,18 @@ void ThreadOptimizerThread() // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { - // 策略 A: 存在重负载辅助线程 (且不是立即执行模式) + DWORD assignedMainCore = settings.idealCore; + DWORD assignedHeavyCore = settings.idealCore; + + // 策略 A: 存在重负载辅助线程 if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); + assignedHeavyCore = settings.idealCore; + assignedMainCore = settings.idealCore - 2; + // 1. 设置重负载线程 -> IdealCore if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { @@ -1124,9 +1192,12 @@ void ThreadOptimizerThread() } } } - // 策略 B: 无重负载辅助线程 (或立即执行模式) + // 策略 B: 无重负载辅助线程 else { + assignedMainCore = settings.idealCore; + assignedHeavyCore = settings.idealCore; + // 清理辅助线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; @@ -1158,6 +1229,74 @@ void ThreadOptimizerThread() } } } + + // --- 策略 C: 优化其余线程 (Ideal Processor) --- + if (settings.optimizeOtherThreads && topology.isInitialized) + { + // 1. 收集其余线程并按负载排序 + std::vector otherThreads; + for (auto& pair : procStats.threads) { + ThreadStats* t = &pair.second; + if (t->threadId == pMainThread->threadId) continue; + if (pHeavyThread && t->threadId == pHeavyThread->threadId) continue; + otherThreads.push_back(t); + } + + std::sort(otherThreads.begin(), otherThreads.end(), [](ThreadStats* a, ThreadStats* b) { + return a->intervalAverageLoad > b->intervalAverageLoad; + }); + + if (!otherThreads.empty()) + { + // 2. 构建分配队列 + std::vector allocationQueue; + + // (1) 性能核心 (正序 排除已占用) + for (DWORD core : topology.pCores) { + if (core == assignedMainCore || core == assignedHeavyCore) continue; + allocationQueue.push_back(core); + } + + // (2) 超线程 (倒序 特殊规则) + std::vector htQueue; + DWORD mainHT = -1; + DWORD heavyHT = -1; + + DWORD mainCoreIndex = topology.lpToCoreIndex.count(assignedMainCore) ? topology.lpToCoreIndex[assignedMainCore] : -1; + DWORD heavyCoreIndex = topology.lpToCoreIndex.count(assignedHeavyCore) ? topology.lpToCoreIndex[assignedHeavyCore] : -1; + + for (DWORD core : topology.htCores) { + DWORD coreIndex = topology.lpToCoreIndex[core]; + if (coreIndex == mainCoreIndex) mainHT = core; + else if (coreIndex == heavyCoreIndex) heavyHT = core; + else htQueue.push_back(core); + } + + std::sort(htQueue.rbegin(), htQueue.rend()); // 倒序 + allocationQueue.insert(allocationQueue.end(), htQueue.begin(), htQueue.end()); + + if (mainHT != -1) allocationQueue.push_back(mainHT); + if (heavyHT != -1 && heavyHT != mainHT) allocationQueue.push_back(heavyHT); + + // (3) 效率核心 (正序) + allocationQueue.insert(allocationQueue.end(), topology.eCores.begin(), topology.eCores.end()); + + // 3. 分配核心 + if (!allocationQueue.empty()) + { + LogColor(COLOR_INFO, " -> [其余线程] 正在为 %zu 个线程分配理想核心 (队列长度: %zu)...\n", otherThreads.size(), allocationQueue.size()); + + for (size_t i = 0; i < otherThreads.size(); ++i) { + DWORD targetCore = allocationQueue[i % allocationQueue.size()]; + HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, otherThreads[i]->threadId); + if (hThread) { + SetThreadIdealProcessor(hThread, targetCore); + CloseHandle(hThread); + } + } + } + } + } } } } From 31c3fa38c2604d7e04dda50328c93146ce46a1fa Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 00:36:36 +0800 Subject: [PATCH 11/23] Add files via upload --- ForegroundBooster.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 1ef47dc..0e63290 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -1286,14 +1286,25 @@ void ThreadOptimizerThread() { LogColor(COLOR_INFO, " -> [其余线程] 正在为 %zu 个线程分配理想核心 (队列长度: %zu)...\n", otherThreads.size(), allocationQueue.size()); + int successCount = 0; for (size_t i = 0; i < otherThreads.size(); ++i) { - DWORD targetCore = allocationQueue[i % allocationQueue.size()]; - HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, otherThreads[i]->threadId); + DWORD targetCore = allocationQueue[i % allocationQueue.size()]; // 循环分配 + + // --- 修正点:必须使用 THREAD_SET_INFORMATION 权限 --- + HANDLE hThread = OpenThread(THREAD_SET_INFORMATION, FALSE, otherThreads[i]->threadId); if (hThread) { - SetThreadIdealProcessor(hThread, targetCore); + if (SetThreadIdealProcessor(hThread, targetCore) != (DWORD)-1) { + successCount++; + // 调试日志 (可选 取消注释以查看详细分配) + LogColor(COLOR_DEFAULT, " Thread %lu -> Core %d\n", otherThreads[i]->threadId, targetCore); + } else { + // 如果失败 尝试记录错误 (通常是权限不足或线程已退出) + LogColor(COLOR_ERROR, " Failed to set ideal processor for thread %lu. Error: %lu\n", otherThreads[i]->threadId, GetLastError()); + } CloseHandle(hThread); } } + LogColor(COLOR_SUCCESS, " -> 成功设置 %d / %zu 个线程的理想核心\n", successCount, otherThreads.size()); } } } From a7f1fd7a869706d6e4a107980ee9e3ef56db261a Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:08:14 +0800 Subject: [PATCH 12/23] Add files via upload --- ForegroundBooster.cpp | 122 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 108 insertions(+), 14 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 0e63290..605f408 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -56,8 +56,9 @@ struct ProcessStats { std::map threads; bool isInitialized; bool ignoreMonitoring; + ULARGE_INTEGER lastOptimizationTime; // --- 新增 --- - ULARGE_INTEGER lastOptimizationTime; // 上次执行 CPU Sets 设置的时间 + ULARGE_INTEGER lastForegroundTime; // 最后一次在前台的时间 // ----------- }; @@ -109,8 +110,9 @@ struct Settings int processListInterval = 60; int idealCore = -1; int cpuSetInterval = 600; + bool optimizeOtherThreads = false; // --- 新增 --- - bool optimizeOtherThreads = false; // 是否优化其余线程 + int cpuSetResetInterval = 300; // 后台重置间隔 默认 300 秒 (5分钟) // ----------- }; Settings settings; @@ -263,6 +265,7 @@ void ParseIniFile(const std::wstring& path) else if (key == L"IdealCore") settings.idealCore = std::stoi(value); else if (key == L"CpuSetInterval") settings.cpuSetInterval = std::stoi(value); else if (key == L"OptimizeOtherThreads") settings.optimizeOtherThreads = (std::stoi(value) != 0); + else if (key == L"CpuSetResetInterval") settings.optimizeOtherThreads = (std::stoi(value) != 0); } } else if (currentSection == L"BlackList") @@ -861,9 +864,10 @@ void AnalyzeCpuTopology(GetSystemCpuSetInformationPtr pGetSystemCpuSetInformatio LogColor(COLOR_INFO, "[拓扑] P核: %zu, HT: %zu, E核: %zu\n", topology.pCores.size(), topology.htCores.size(), topology.eCores.size()); } +using GetProcessDefaultCpuSetsPtr = BOOL(WINAPI*)(HANDLE, PULONG, ULONG, PULONG); + void ThreadOptimizerThread() { - // --- 加载 API --- HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); @@ -871,6 +875,10 @@ void ThreadOptimizerThread() (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); + // --- 新增 --- + GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = + (GetProcessDefaultCpuSetsPtr)GetProcAddress(hKernel32, "GetProcessDefaultCpuSets"); + // ----------- NtQueryInformationThreadPtr pNtQueryInformationThread = (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); @@ -879,7 +887,6 @@ void ThreadOptimizerThread() LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+) 优化功能受限\n"); } - // --- 预先解析 IdealCore 对应的 CpuSetId --- ULONG idealCoreCpuSetId = 0; ULONG mainThreadFallbackCpuSetId = 0; @@ -890,38 +897,125 @@ void ThreadOptimizerThread() } } - // --- 初始化拓扑结构 --- + // --- 新增:拓扑结构 --- CpuTopology topology; + // -------------------- + DWORD previousPid = 0; while (true) { - // 1. 持续监控:每秒唤醒一次 std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; + // 注意:即使 currentPid 为 0 我们也可能需要执行清理逻辑 所以这里不直接 continue + // 但为了保持逻辑简单 我们假设总有一个前台进程如果 currentPid 为 0 我们只跳过优化部分 + + FILETIME ftSystem; + GetSystemTimeAsFileTime(&ftSystem); + ULARGE_INTEGER now = FT2ULL(ftSystem); + + // --- 新增:后台进程清理逻辑 --- + if (settings.cpuSetResetInterval > 0 && pSetThreadSelectedCpuSets) + { + std::lock_guard lock(g_statsMutex); + ULONGLONG resetThreshold = (ULONGLONG)settings.cpuSetResetInterval * 10000000ULL; + + for (auto& procPair : g_processStatsCache) + { + DWORD pid = procPair.first; + ProcessStats& pStats = procPair.second; + + // 1. 如果是当前前台进程 更新时间戳 + if (pid == currentPid) + { + pStats.lastForegroundTime = now; + continue; // 跳过清理检查 + } + + // 2. 检查后台超时 + // 确保 lastForegroundTime 已初始化 (非0) + if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) + { + ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; + + if (timeInBg > resetThreshold) + { + bool anyReset = false; + // 遍历该进程的所有线程 + for (auto& threadPair : pStats.threads) + { + ThreadStats& tStats = threadPair.second; + + // 如果该线程被标记为设置了 CPU Sets + if (tStats.hasCpuSets) + { + HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, tStats.threadId); + if (hThread) + { + // 清空 CPU Sets (传入 NULL, 0) + if (pSetThreadSelectedCpuSets(hThread, NULL, 0)) + { + anyReset = true; + } + CloseHandle(hThread); + } + // 无论 API 调用是否成功(可能线程已死) 都重置标记 避免重复尝试 + tStats.hasCpuSets = false; + tStats.assignedCpuSetId = 0; + } + } + + if (anyReset) + { + LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒 重置其线程 CPU Sets\n", + pid, settings.cpuSetResetInterval); + // 更新时间戳以避免在下一秒重复触发日志 (虽然 hasCpuSets 已经 false 了) + pStats.lastForegroundTime = now; + } + } + } + } + } + // --------------------------- + if (currentPid == 0) continue; - // --- 快速检查:是否忽略 --- + // --- 1. 快速检查:是否已标记为忽略 --- { std::lock_guard lock(g_statsMutex); if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) continue; } - // --- 亲和性检查 --- - bool customAffinityDetected = false; - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, currentPid); + // --- 2. 亲和性与 CPU Sets 检查 --- + bool customConfigDetected = false; + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, currentPid); if (hProcess) { + // A. 检查亲和性 DWORD_PTR processAffinity, systemAffinity; if (GetProcessAffinityMask(hProcess, &processAffinity, &systemAffinity)) { - if (processAffinity != systemAffinity) customAffinityDetected = true; + if (processAffinity != systemAffinity) customConfigDetected = true; + } + + // B. 检查进程 CPU Sets (如果亲和性正常 且 API 可用) + if (!customConfigDetected && pGetProcessDefaultCpuSets) + { + ULONG requiredIdCount = 0; + // 调用一次以获取 ID 数量 如果数量 > 0 说明设置了 CPU Sets + pGetProcessDefaultCpuSets(hProcess, NULL, 0, &requiredIdCount); + if (requiredIdCount > 0) + { + customConfigDetected = true; + } } + CloseHandle(hProcess); } - if (customAffinityDetected) + // 如果检测到自定义配置 (亲和性 或 CPU Sets) 停止监控 + if (customConfigDetected) { std::lock_guard lock(g_statsMutex); ProcessStats& procStats = g_processStatsCache[currentPid]; @@ -930,7 +1024,7 @@ void ThreadOptimizerThread() { procStats.ignoreMonitoring = true; procStats.threads.clear(); - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置亲和性 停止追踪其线程负载\n", currentPid); + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置设置亲和性或 CPU Sets 停止追踪其线程负载\n", currentPid); } continue; } @@ -1231,7 +1325,7 @@ void ThreadOptimizerThread() } // --- 策略 C: 优化其余线程 (Ideal Processor) --- - if (settings.optimizeOtherThreads && topology.isInitialized) + if (settings.optimizeOtherThreads && topology.isInitialized && !isImmediateRun) { // 1. 收集其余线程并按负载排序 std::vector otherThreads; From 7ae85d0987b8945fafd226a6ba693092c5056162 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:12:53 +0800 Subject: [PATCH 13/23] Add files via upload --- ForegroundBooster.cpp | 119 +++++++++++------------------------------- 1 file changed, 30 insertions(+), 89 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 605f408..a6b0665 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -875,10 +875,8 @@ void ThreadOptimizerThread() (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); - // --- 新增 --- GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = (GetProcessDefaultCpuSetsPtr)GetProcAddress(hKernel32, "GetProcessDefaultCpuSets"); - // ----------- NtQueryInformationThreadPtr pNtQueryInformationThread = (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); @@ -897,10 +895,7 @@ void ThreadOptimizerThread() } } - // --- 新增:拓扑结构 --- CpuTopology topology; - // -------------------- - DWORD previousPid = 0; while (true) @@ -908,14 +903,14 @@ void ThreadOptimizerThread() std::this_thread::sleep_for(std::chrono::seconds(1)); DWORD currentPid = lastProcessId; - // 注意:即使 currentPid 为 0 我们也可能需要执行清理逻辑 所以这里不直接 continue - // 但为了保持逻辑简单 我们假设总有一个前台进程如果 currentPid 为 0 我们只跳过优化部分 + // --- 修正点 1: 在循环顶部统一定义时间变量 --- FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); + // ------------------------------------------- - // --- 新增:后台进程清理逻辑 --- + // --- 后台进程清理逻辑 --- if (settings.cpuSetResetInterval > 0 && pSetThreadSelectedCpuSets) { std::lock_guard lock(g_statsMutex); @@ -926,15 +921,12 @@ void ThreadOptimizerThread() DWORD pid = procPair.first; ProcessStats& pStats = procPair.second; - // 1. 如果是当前前台进程 更新时间戳 if (pid == currentPid) { pStats.lastForegroundTime = now; - continue; // 跳过清理检查 + continue; } - // 2. 检查后台超时 - // 确保 lastForegroundTime 已初始化 (非0) if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; @@ -942,25 +934,17 @@ void ThreadOptimizerThread() if (timeInBg > resetThreshold) { bool anyReset = false; - // 遍历该进程的所有线程 for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; - - // 如果该线程被标记为设置了 CPU Sets if (tStats.hasCpuSets) { HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, tStats.threadId); if (hThread) { - // 清空 CPU Sets (传入 NULL, 0) - if (pSetThreadSelectedCpuSets(hThread, NULL, 0)) - { - anyReset = true; - } + if (pSetThreadSelectedCpuSets(hThread, NULL, 0)) anyReset = true; CloseHandle(hThread); } - // 无论 API 调用是否成功(可能线程已死) 都重置标记 避免重复尝试 tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } @@ -968,53 +952,43 @@ void ThreadOptimizerThread() if (anyReset) { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒 重置其线程 CPU Sets\n", + LogColor(COLOR_WARNING, "[清理] 进程 %lu 在后台超过 %d 秒 已重置其线程 CPU Sets\n", pid, settings.cpuSetResetInterval); - // 更新时间戳以避免在下一秒重复触发日志 (虽然 hasCpuSets 已经 false 了) pStats.lastForegroundTime = now; } } } } } - // --------------------------- if (currentPid == 0) continue; - // --- 1. 快速检查:是否已标记为忽略 --- + // --- 快速检查:是否忽略 --- { std::lock_guard lock(g_statsMutex); if (g_processStatsCache.count(currentPid) && g_processStatsCache[currentPid].ignoreMonitoring) continue; } - // --- 2. 亲和性与 CPU Sets 检查 --- + // --- 亲和性与 CPU Sets 检查 --- bool customConfigDetected = false; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, currentPid); if (hProcess) { - // A. 检查亲和性 DWORD_PTR processAffinity, systemAffinity; if (GetProcessAffinityMask(hProcess, &processAffinity, &systemAffinity)) { if (processAffinity != systemAffinity) customConfigDetected = true; } - // B. 检查进程 CPU Sets (如果亲和性正常 且 API 可用) if (!customConfigDetected && pGetProcessDefaultCpuSets) { ULONG requiredIdCount = 0; - // 调用一次以获取 ID 数量 如果数量 > 0 说明设置了 CPU Sets pGetProcessDefaultCpuSets(hProcess, NULL, 0, &requiredIdCount); - if (requiredIdCount > 0) - { - customConfigDetected = true; - } + if (requiredIdCount > 0) customConfigDetected = true; } - CloseHandle(hProcess); } - // 如果检测到自定义配置 (亲和性 或 CPU Sets) 停止监控 if (customConfigDetected) { std::lock_guard lock(g_statsMutex); @@ -1024,19 +998,19 @@ void ThreadOptimizerThread() { procStats.ignoreMonitoring = true; procStats.threads.clear(); - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置设置亲和性或 CPU Sets 停止追踪其线程负载\n", currentPid); + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置亲和性或 CPU Sets 停止追踪其线程负载\n", currentPid); } continue; } - // --- 初始化拓扑 (仅一次) --- + // --- 在循环内部初始化拓扑 (仅一次) --- if (!topology.isInitialized && pGetSystemCpuSetInformation) { AnalyzeCpuTopology(pGetSystemCpuSetInformation, topology); } - FILETIME ftSystem; - GetSystemTimeAsFileTime(&ftSystem); - ULARGE_INTEGER now = FT2ULL(ftSystem); + // --- 修正点 2: 删除了此处重复定义的 ftSystem 和 now --- + // (原代码这里有重复定义 导致编译错误) + // --------------------------------------------------- HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot == INVALID_HANDLE_VALUE) continue; @@ -1050,19 +1024,20 @@ void ThreadOptimizerThread() ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; + // 再次更新前台时间 防止清理逻辑误判 (双重保险) + procStats.lastForegroundTime = now; + // --- 检测前台切换 --- if (currentPid != previousPid) { if (procStats.lastOptimizationTime.QuadPart == 0) { - LogColor(COLOR_INFO, "[监控] 新进程 %lu 立即执行首次优化\n", currentPid); + LogColor(COLOR_INFO, "[监控] 新进程 %lu 将立即执行首次优化\n", currentPid); } else { LogColor(COLOR_INFO, "[监控] 旧进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); - procStats.lastOptimizationTime = now; // 重置计时器 - - // 重置快照 + procStats.lastOptimizationTime = now; for (auto& pair : procStats.threads) { pair.second.intervalStartTime = now; pair.second.intervalStartKernelTime = pair.second.lastKernelTime; @@ -1100,7 +1075,6 @@ void ThreadOptimizerThread() ts.lastKernelTime = FT2ULL(ftKernel); ts.lastUserTime = FT2ULL(ftUser); ts.lastCheckTime = now; - ts.intervalStartKernelTime = ts.lastKernelTime; ts.intervalStartUserTime = ts.lastUserTime; ts.intervalStartTime = now; @@ -1137,7 +1111,6 @@ void ThreadOptimizerThread() } while (Thread32Next(hSnapshot, &te32)); } - // 清理已退出的线程 for (auto it = procStats.threads.begin(); it != procStats.threads.end(); ) { bool exists = false; @@ -1148,17 +1121,18 @@ void ThreadOptimizerThread() else ++it; } - // --- 检查是否达到优化间隔 --- ULONGLONG timeSinceLastOpt = now.QuadPart - procStats.lastOptimizationTime.QuadPart; ULONGLONG intervalUnits = (ULONGLONG)settings.cpuSetInterval * 10000000ULL; if (timeSinceLastOpt >= intervalUnits) { bool isImmediateRun = (procStats.lastOptimizationTime.QuadPart == 0); - if (isImmediateRun) LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); - else LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); + if (isImmediateRun) { + LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); + } else { + LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); + } - // 1. 计算平均负载 for (auto& pair : procStats.threads) { ThreadStats& ts = pair.second; @@ -1166,14 +1140,11 @@ void ThreadOptimizerThread() ts.intervalAverageLoad = 0.0; continue; } - ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + (ts.lastUserTime.QuadPart - ts.intervalStartUserTime.QuadPart); - if (timeDelta > 0) ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; else ts.intervalAverageLoad = 0.0; - ts.intervalStartKernelTime = ts.lastKernelTime; ts.intervalStartUserTime = ts.lastUserTime; ts.intervalStartTime = now; @@ -1181,7 +1152,6 @@ void ThreadOptimizerThread() procStats.lastOptimizationTime = now; - // 2. 识别线程 ThreadStats* pMainThread = nullptr; ThreadStats* pHeavyThread = nullptr; @@ -1207,7 +1177,6 @@ void ThreadOptimizerThread() if (pMainThread) pMainThread->isMainThread = true; - // --- 辅助 Lambda: 亲和性修正 --- auto EnsureCoreInAffinity = [&](HANDLE hThread, DWORD coreIndex) { if (!pNtQueryInformationThread) return; THREAD_BASIC_INFORMATION tbi; @@ -1221,25 +1190,18 @@ void ThreadOptimizerThread() } }; - // --- 执行优化策略 --- if (settings.idealCore >= 0 && pMainThread && pSetThreadSelectedCpuSets && idealCoreCpuSetId != 0) { DWORD assignedMainCore = settings.idealCore; DWORD assignedHeavyCore = settings.idealCore; - // 策略 A: 存在重负载辅助线程 if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); - assignedHeavyCore = settings.idealCore; - assignedMainCore = settings.idealCore - 2; - - // 1. 设置重负载线程 -> IdealCore if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) { - // 清理其他线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { @@ -1267,7 +1229,6 @@ void ThreadOptimizerThread() } } - // 2. 设置主线程 -> IdealCore - 2 if (mainThreadFallbackCpuSetId != 0 && pMainThread->assignedCpuSetId != mainThreadFallbackCpuSetId) { HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION, FALSE, pMainThread->threadId); @@ -1285,14 +1246,11 @@ void ThreadOptimizerThread() CloseHandle(hMain); } } + assignedHeavyCore = settings.idealCore; + assignedMainCore = settings.idealCore - 2; } - // 策略 B: 无重负载辅助线程 else { - assignedMainCore = settings.idealCore; - assignedHeavyCore = settings.idealCore; - - // 清理辅助线程 for (auto& pair : procStats.threads) { ThreadStats& t = pair.second; if (t.threadId != pMainThread->threadId && t.hasCpuSets && t.assignedCpuSetId != 0) { @@ -1305,7 +1263,6 @@ void ThreadOptimizerThread() } } - // 设置主线程 -> IdealCore if (!pMainThread->hasCpuSets || pMainThread->assignedCpuSetId != idealCoreCpuSetId) { HANDLE hMain = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION, FALSE, pMainThread->threadId); @@ -1322,12 +1279,12 @@ void ThreadOptimizerThread() CloseHandle(hMain); } } + assignedMainCore = settings.idealCore; + assignedHeavyCore = settings.idealCore; } - // --- 策略 C: 优化其余线程 (Ideal Processor) --- if (settings.optimizeOtherThreads && topology.isInitialized && !isImmediateRun) { - // 1. 收集其余线程并按负载排序 std::vector otherThreads; for (auto& pair : procStats.threads) { ThreadStats* t = &pair.second; @@ -1335,27 +1292,21 @@ void ThreadOptimizerThread() if (pHeavyThread && t->threadId == pHeavyThread->threadId) continue; otherThreads.push_back(t); } - std::sort(otherThreads.begin(), otherThreads.end(), [](ThreadStats* a, ThreadStats* b) { return a->intervalAverageLoad > b->intervalAverageLoad; }); if (!otherThreads.empty()) { - // 2. 构建分配队列 std::vector allocationQueue; - - // (1) 性能核心 (正序 排除已占用) for (DWORD core : topology.pCores) { if (core == assignedMainCore || core == assignedHeavyCore) continue; allocationQueue.push_back(core); } - // (2) 超线程 (倒序 特殊规则) std::vector htQueue; DWORD mainHT = -1; DWORD heavyHT = -1; - DWORD mainCoreIndex = topology.lpToCoreIndex.count(assignedMainCore) ? topology.lpToCoreIndex[assignedMainCore] : -1; DWORD heavyCoreIndex = topology.lpToCoreIndex.count(assignedHeavyCore) ? topology.lpToCoreIndex[assignedHeavyCore] : -1; @@ -1366,34 +1317,24 @@ void ThreadOptimizerThread() else htQueue.push_back(core); } - std::sort(htQueue.rbegin(), htQueue.rend()); // 倒序 + std::sort(htQueue.rbegin(), htQueue.rend()); allocationQueue.insert(allocationQueue.end(), htQueue.begin(), htQueue.end()); if (mainHT != -1) allocationQueue.push_back(mainHT); if (heavyHT != -1 && heavyHT != mainHT) allocationQueue.push_back(heavyHT); - // (3) 效率核心 (正序) allocationQueue.insert(allocationQueue.end(), topology.eCores.begin(), topology.eCores.end()); - // 3. 分配核心 if (!allocationQueue.empty()) { LogColor(COLOR_INFO, " -> [其余线程] 正在为 %zu 个线程分配理想核心 (队列长度: %zu)...\n", otherThreads.size(), allocationQueue.size()); - int successCount = 0; for (size_t i = 0; i < otherThreads.size(); ++i) { - DWORD targetCore = allocationQueue[i % allocationQueue.size()]; // 循环分配 - - // --- 修正点:必须使用 THREAD_SET_INFORMATION 权限 --- + DWORD targetCore = allocationQueue[i % allocationQueue.size()]; HANDLE hThread = OpenThread(THREAD_SET_INFORMATION, FALSE, otherThreads[i]->threadId); if (hThread) { if (SetThreadIdealProcessor(hThread, targetCore) != (DWORD)-1) { successCount++; - // 调试日志 (可选 取消注释以查看详细分配) - LogColor(COLOR_DEFAULT, " Thread %lu -> Core %d\n", otherThreads[i]->threadId, targetCore); - } else { - // 如果失败 尝试记录错误 (通常是权限不足或线程已退出) - LogColor(COLOR_ERROR, " Failed to set ideal processor for thread %lu. Error: %lu\n", otherThreads[i]->threadId, GetLastError()); } CloseHandle(hThread); } From 599a1110c30e2e72e448b28e05b05474f8f3f6ac Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:26:10 +0800 Subject: [PATCH 14/23] Add files via upload --- ForegroundBooster.cpp | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index a6b0665..574a935 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -921,30 +921,57 @@ void ThreadOptimizerThread() DWORD pid = procPair.first; ProcessStats& pStats = procPair.second; + // 1. 如果是当前前台进程,更新时间戳并跳过 if (pid == currentPid) { pStats.lastForegroundTime = now; - continue; + continue; } + // 2. 检查后台超时 if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; - + if (timeInBg > resetThreshold) { bool anyReset = false; for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; + + // 只要设置过 CPU Sets,或者我们想确保清理干净 if (tStats.hasCpuSets) { - HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, tStats.threadId); + // 使用更完整的权限打开线程 + HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION, FALSE, tStats.threadId); if (hThread) { - if (pSetThreadSelectedCpuSets(hThread, NULL, 0)) anyReset = true; + // 1. 清空 CPU Sets (传入 NULL, 0) + BOOL cpuSetReset = pSetThreadSelectedCpuSets(hThread, NULL, 0); + + // 2. 重置理想处理器 (传入 MAXIMUM_PROCESSORS 表示取消设置) + DWORD idealReset = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); + + if (cpuSetReset) + { + anyReset = true; + // 可选:记录详细调试日志 + LogColor(COLOR_DEFAULT, " -> 线程 %lu CPU Sets 已重置。\n", tStats.threadId); + } + else + { + LogColor(COLOR_ERROR, " -> [错误] 无法重置线程 %lu 的 CPU Sets。错误码: %lu\n", tStats.threadId, GetLastError()); + } + CloseHandle(hThread); } + else + { + // 线程可能已退出,无法打开句柄 + } + + // 无论成功与否,清除标记以避免重复尝试 tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } @@ -952,9 +979,11 @@ void ThreadOptimizerThread() if (anyReset) { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 在后台超过 %d 秒 已重置其线程 CPU Sets\n", + LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,已重置其所有线程的 CPU Sets 和理想核心。\n", pid, settings.cpuSetResetInterval); - pStats.lastForegroundTime = now; + + // 更新时间戳,防止日志刷屏 (虽然 hasCpuSets 已清除,但这是一个好的实践) + pStats.lastForegroundTime = now; } } } From 687aaae22961c6501522849fc22135d51e257aa4 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:31:22 +0800 Subject: [PATCH 15/23] Add files via upload --- ForegroundBooster.cpp | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 574a935..5904981 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -929,60 +929,65 @@ void ThreadOptimizerThread() } // 2. 检查后台超时 + // 必须确保 lastForegroundTime 已被初始化 (>0),否则忽略从未在前台出现过的进程 if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; if (timeInBg > resetThreshold) { - bool anyReset = false; + bool triggeredReset = false; // 只要尝试了重置,就标记为真 + int resetCount = 0; + for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; - // 只要设置过 CPU Sets,或者我们想确保清理干净 + // 检查是否标记为已设置 CPU Sets if (tStats.hasCpuSets) { - // 使用更完整的权限打开线程 + triggeredReset = true; // 标记触发 + + // 尝试打开线程句柄 HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION, FALSE, tStats.threadId); if (hThread) { - // 1. 清空 CPU Sets (传入 NULL, 0) - BOOL cpuSetReset = pSetThreadSelectedCpuSets(hThread, NULL, 0); + // 1. 清空 CPU Sets + BOOL cpuSetResult = pSetThreadSelectedCpuSets(hThread, NULL, 0); - // 2. 重置理想处理器 (传入 MAXIMUM_PROCESSORS 表示取消设置) - DWORD idealReset = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); + // 2. 重置理想处理器 + DWORD idealResult = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); - if (cpuSetReset) + if (cpuSetResult) { - anyReset = true; - // 可选:记录详细调试日志 - LogColor(COLOR_DEFAULT, " -> 线程 %lu CPU Sets 已重置。\n", tStats.threadId); + resetCount++; } else { - LogColor(COLOR_ERROR, " -> [错误] 无法重置线程 %lu 的 CPU Sets。错误码: %lu\n", tStats.threadId, GetLastError()); + // 输出 API 调用失败的错误日志 + LogColor(COLOR_ERROR, " -> [错误] 重置线程 %lu 失败。错误码: %lu\n", tStats.threadId, GetLastError()); } CloseHandle(hThread); } else { - // 线程可能已退出,无法打开句柄 + // 线程可能已退出,无法打开句柄,这是正常现象,但我们也记录一下 + LogColor(COLOR_WARNING, " -> [警告] 无法打开线程 %lu (可能已退出)。\n", tStats.threadId); } - // 无论成功与否,清除标记以避免重复尝试 + // 无论成功与否,都清除标记,避免死循环尝试 tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } } - if (anyReset) + if (triggeredReset) { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,已重置其所有线程的 CPU Sets 和理想核心。\n", - pid, settings.cpuSetResetInterval); + LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,触发重置 (成功重置 %d 个线程)。\n", + pid, settings.cpuSetResetInterval, resetCount); - // 更新时间戳,防止日志刷屏 (虽然 hasCpuSets 已清除,但这是一个好的实践) + // 更新时间戳,防止日志在下一秒重复输出 pStats.lastForegroundTime = now; } } From e9a97fad32e3e545bb32005de20f5680a92242e2 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:37:13 +0800 Subject: [PATCH 16/23] Add files via upload --- ForegroundBooster.cpp | 134 +++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 72 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 5904981..4e565a3 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -871,22 +871,22 @@ void ThreadOptimizerThread() HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); - SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = + SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); - GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = + GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); - GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = + GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = (GetProcessDefaultCpuSetsPtr)GetProcAddress(hKernel32, "GetProcessDefaultCpuSets"); - NtQueryInformationThreadPtr pNtQueryInformationThread = + NtQueryInformationThreadPtr pNtQueryInformationThread = (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+) 优化功能受限\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),优化功能受限。\n"); } - ULONG idealCoreCpuSetId = 0; - ULONG mainThreadFallbackCpuSetId = 0; + ULONG idealCoreCpuSetId = 0; + ULONG mainThreadFallbackCpuSetId = 0; if (settings.idealCore >= 0 && pGetSystemCpuSetInformation) { idealCoreCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); @@ -896,7 +896,7 @@ void ThreadOptimizerThread() } CpuTopology topology; - DWORD previousPid = 0; + DWORD previousPid = 0; while (true) { @@ -904,13 +904,11 @@ void ThreadOptimizerThread() DWORD currentPid = lastProcessId; - // --- 修正点 1: 在循环顶部统一定义时间变量 --- FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); - // ------------------------------------------- - // --- 后台进程清理逻辑 --- + // --- 后台进程清理逻辑 (带诊断日志) --- if (settings.cpuSetResetInterval > 0 && pSetThreadSelectedCpuSets) { std::lock_guard lock(g_statsMutex); @@ -928,55 +926,45 @@ void ThreadOptimizerThread() continue; } - // 2. 检查后台超时 - // 必须确保 lastForegroundTime 已被初始化 (>0),否则忽略从未在前台出现过的进程 - if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) + // 2. 初始化时间戳 (防止新进程为0) + if (pStats.lastForegroundTime.QuadPart == 0) + { + pStats.lastForegroundTime = now; + continue; + } + + // 3. 检查后台超时 + if (now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; if (timeInBg > resetThreshold) { - bool triggeredReset = false; // 只要尝试了重置,就标记为真 + // 触发超时,先输出诊断信息 + // LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %llu 秒 (阈值 %d),正在检查线程状态...\n", pid, timeInBg / 10000000, settings.cpuSetResetInterval); + + bool triggeredReset = false; int resetCount = 0; for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; - // 检查是否标记为已设置 CPU Sets if (tStats.hasCpuSets) { - triggeredReset = true; // 标记触发 - - // 尝试打开线程句柄 + triggeredReset = true; HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION, FALSE, tStats.threadId); if (hThread) { - // 1. 清空 CPU Sets - BOOL cpuSetResult = pSetThreadSelectedCpuSets(hThread, NULL, 0); + // 清空 CPU Sets 和 理想核心 + BOOL b1 = pSetThreadSelectedCpuSets(hThread, NULL, 0); + DWORD d2 = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); - // 2. 重置理想处理器 - DWORD idealResult = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); - - if (cpuSetResult) - { - resetCount++; - } - else - { - // 输出 API 调用失败的错误日志 - LogColor(COLOR_ERROR, " -> [错误] 重置线程 %lu 失败。错误码: %lu\n", tStats.threadId, GetLastError()); - } - + if (b1) resetCount++; CloseHandle(hThread); } - else - { - // 线程可能已退出,无法打开句柄,这是正常现象,但我们也记录一下 - LogColor(COLOR_WARNING, " -> [警告] 无法打开线程 %lu (可能已退出)。\n", tStats.threadId); - } - - // 无论成功与否,都清除标记,避免死循环尝试 + + // 清除标记 tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } @@ -984,16 +972,22 @@ void ThreadOptimizerThread() if (triggeredReset) { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,触发重置 (成功重置 %d 个线程)。\n", + LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,已重置 %d 个线程的 CPU Sets。\n", pid, settings.cpuSetResetInterval, resetCount); - - // 更新时间戳,防止日志在下一秒重复输出 - pStats.lastForegroundTime = now; } + else + { + // 如果没有线程需要重置,也记录一下,证明逻辑跑通了 + // LogColor(COLOR_DEFAULT, " -> [诊断] 进程 %lu 无需重置 (未设置 CPU Sets)。\n", pid); + } + + // 更新时间戳,避免下一秒重复检查 + pStats.lastForegroundTime = now; } } } } + // ------------------------------------ if (currentPid == 0) continue; @@ -1032,7 +1026,7 @@ void ThreadOptimizerThread() { procStats.ignoreMonitoring = true; procStats.threads.clear(); - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置亲和性或 CPU Sets 停止追踪其线程负载\n", currentPid); + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性或 CPU Sets,停止追踪其线程负载。\n", currentPid); } continue; } @@ -1042,10 +1036,6 @@ void ThreadOptimizerThread() AnalyzeCpuTopology(pGetSystemCpuSetInformation, topology); } - // --- 修正点 2: 删除了此处重复定义的 ftSystem 和 now --- - // (原代码这里有重复定义 导致编译错误) - // --------------------------------------------------- - HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot == INVALID_HANDLE_VALUE) continue; @@ -1057,8 +1047,8 @@ void ThreadOptimizerThread() std::lock_guard lock(g_statsMutex); ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; - - // 再次更新前台时间 防止清理逻辑误判 (双重保险) + + // 再次更新前台时间 (双重保险) procStats.lastForegroundTime = now; // --- 检测前台切换 --- @@ -1066,12 +1056,12 @@ void ThreadOptimizerThread() { if (procStats.lastOptimizationTime.QuadPart == 0) { - LogColor(COLOR_INFO, "[监控] 新进程 %lu 将立即执行首次优化\n", currentPid); + LogColor(COLOR_INFO, "[监控] 新进程 %lu (无缓存),将立即执行首次优化 (仅主线程)。\n", currentPid); } else { - LogColor(COLOR_INFO, "[监控] 旧进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); - procStats.lastOptimizationTime = now; + LogColor(COLOR_INFO, "[监控] 旧进程 %lu (有缓存),将在 %d 秒后应用优化。\n", currentPid, settings.cpuSetInterval); + procStats.lastOptimizationTime = now; for (auto& pair : procStats.threads) { pair.second.intervalStartTime = now; pair.second.intervalStartKernelTime = pair.second.lastKernelTime; @@ -1092,14 +1082,14 @@ void ThreadOptimizerThread() currentThreadIds.push_back(tid); bool isNewThread = (procStats.threads.find(tid) == procStats.threads.end()); - + if (isNewThread) { ThreadStats ts = {}; ts.threadId = tid; ts.hasCpuSets = false; ts.assignedCpuSetId = 0; - + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); if (hThread) { @@ -1129,8 +1119,8 @@ void ThreadOptimizerThread() ts.lastKernelTime = FT2ULL(ftKernel); ts.lastUserTime = FT2ULL(ftUser); ts.lastCheckTime = now; - - if (procStats.lastOptimizationTime.QuadPart != 0 && + + if (procStats.lastOptimizationTime.QuadPart != 0 && ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) { ts.intervalStartKernelTime = ts.lastKernelTime; @@ -1162,9 +1152,9 @@ void ThreadOptimizerThread() { bool isImmediateRun = (procStats.lastOptimizationTime.QuadPart == 0); if (isImmediateRun) { - LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); + LogColor(COLOR_INFO, "[分析] 触发新进程立即优化 (仅设置主线程)...\n"); } else { - LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); + LogColor(COLOR_INFO, "[分析] 观察周期结束,正在计算平均负载并应用优化...\n"); } for (auto& pair : procStats.threads) @@ -1175,7 +1165,7 @@ void ThreadOptimizerThread() continue; } ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; - ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + + ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + (ts.lastUserTime.QuadPart - ts.intervalStartUserTime.QuadPart); if (timeDelta > 0) ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; else ts.intervalAverageLoad = 0.0; @@ -1195,7 +1185,7 @@ void ThreadOptimizerThread() if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) pMainThread = &t; } - + if (!isImmediateRun) { for (auto& pair : procStats.threads) @@ -1231,7 +1221,7 @@ void ThreadOptimizerThread() if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { - LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", + LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%),执行分离策略。\n", pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) @@ -1255,7 +1245,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu\n", pHeavyThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu。\n", pHeavyThread->threadId, idealCoreCpuSetId); pHeavyThread->hasCpuSets = true; pHeavyThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1272,7 +1262,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { mainThreadFallbackCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)\n", + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)。\n", pMainThread->threadId, mainThreadFallbackCpuSetId, settings.idealCore - 2); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = mainThreadFallbackCpuSetId; @@ -1306,7 +1296,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu\n", pMainThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu。\n", pMainThread->threadId, idealCoreCpuSetId); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1353,7 +1343,7 @@ void ThreadOptimizerThread() std::sort(htQueue.rbegin(), htQueue.rend()); allocationQueue.insert(allocationQueue.end(), htQueue.begin(), htQueue.end()); - + if (mainHT != -1) allocationQueue.push_back(mainHT); if (heavyHT != -1 && heavyHT != mainHT) allocationQueue.push_back(heavyHT); @@ -1364,7 +1354,7 @@ void ThreadOptimizerThread() LogColor(COLOR_INFO, " -> [其余线程] 正在为 %zu 个线程分配理想核心 (队列长度: %zu)...\n", otherThreads.size(), allocationQueue.size()); int successCount = 0; for (size_t i = 0; i < otherThreads.size(); ++i) { - DWORD targetCore = allocationQueue[i % allocationQueue.size()]; + DWORD targetCore = allocationQueue[i % allocationQueue.size()]; HANDLE hThread = OpenThread(THREAD_SET_INFORMATION, FALSE, otherThreads[i]->threadId); if (hThread) { if (SetThreadIdealProcessor(hThread, targetCore) != (DWORD)-1) { @@ -1373,14 +1363,14 @@ void ThreadOptimizerThread() CloseHandle(hThread); } } - LogColor(COLOR_SUCCESS, " -> 成功设置 %d / %zu 个线程的理想核心\n", successCount, otherThreads.size()); + LogColor(COLOR_SUCCESS, " -> 成功设置了 %d / %zu 个线程的理想核心。\n", successCount, otherThreads.size()); } } } } } - } - + } + CloseHandle(hSnapshot); } } From ee2f90b02a33ba28362e3c31422825856417ed45 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:38:29 +0800 Subject: [PATCH 17/23] Add files via upload --- ForegroundBooster.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 4e565a3..994a355 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -941,7 +941,7 @@ void ThreadOptimizerThread() if (timeInBg > resetThreshold) { // 触发超时,先输出诊断信息 - // LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %llu 秒 (阈值 %d),正在检查线程状态...\n", pid, timeInBg / 10000000, settings.cpuSetResetInterval); + LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %llu 秒 (阈值 %d),正在检查线程状态...\n", pid, timeInBg / 10000000, settings.cpuSetResetInterval); bool triggeredReset = false; int resetCount = 0; @@ -978,7 +978,7 @@ void ThreadOptimizerThread() else { // 如果没有线程需要重置,也记录一下,证明逻辑跑通了 - // LogColor(COLOR_DEFAULT, " -> [诊断] 进程 %lu 无需重置 (未设置 CPU Sets)。\n", pid); + LogColor(COLOR_DEFAULT, " -> [诊断] 进程 %lu 无需重置 (未设置 CPU Sets)。\n", pid); } // 更新时间戳,避免下一秒重复检查 From 494a1c3dab2f46df11c0cc7be0d8ccad795faaa1 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:43:58 +0800 Subject: [PATCH 18/23] Add files via upload --- ForegroundBooster.cpp | 81 ++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 994a355..d3066d6 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -880,9 +880,14 @@ void ThreadOptimizerThread() NtQueryInformationThreadPtr pNtQueryInformationThread = (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); + // --- [调试] 启动自检 --- + LogColor(COLOR_INFO, "[调试] 优化线程启动。\n"); + LogColor(COLOR_INFO, "[调试] API SetThreadSelectedCpuSets: %p\n", pSetThreadSelectedCpuSets); + LogColor(COLOR_INFO, "[调试] 配置 CpuSetResetInterval: %d\n", settings.cpuSetResetInterval); + if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+),优化功能受限。\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+)。\n"); } ULONG idealCoreCpuSetId = 0; @@ -897,6 +902,7 @@ void ThreadOptimizerThread() CpuTopology topology; DWORD previousPid = 0; + int debugLogCounter = 0; // 用于控制调试日志频率 while (true) { @@ -908,47 +914,71 @@ void ThreadOptimizerThread() GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); - // --- 后台进程清理逻辑 (带诊断日志) --- - if (settings.cpuSetResetInterval > 0 && pSetThreadSelectedCpuSets) + // --- 1. 优先更新当前前台进程的时间戳 --- + if (currentPid != 0) + { + std::lock_guard lock(g_statsMutex); + // 如果缓存中还没有这个进程,这里不会插入,会在下面的优化逻辑中插入 + // 但如果有了,必须立即更新,防止被误杀 + if (g_processStatsCache.count(currentPid)) { + g_processStatsCache[currentPid].lastForegroundTime = now; + } + } + + // --- 2. 后台进程清理逻辑 --- + // 移除 pSetThreadSelectedCpuSets 检查,即使 API 不存在也输出日志以便调试 + if (settings.cpuSetResetInterval > 0) { std::lock_guard lock(g_statsMutex); ULONGLONG resetThreshold = (ULONGLONG)settings.cpuSetResetInterval * 10000000ULL; + // [调试] 每5秒输出一次缓存状态 + if (++debugLogCounter % 5 == 0) { + LogColor(COLOR_DEFAULT, "[调试] 正在检查后台清理... 缓存进程数: %zu, 当前前台: %lu\n", g_processStatsCache.size(), currentPid); + } + for (auto& procPair : g_processStatsCache) { DWORD pid = procPair.first; ProcessStats& pStats = procPair.second; - // 1. 如果是当前前台进程,更新时间戳并跳过 - if (pid == currentPid) - { - pStats.lastForegroundTime = now; - continue; - } + // 跳过当前前台进程 + if (pid == currentPid) continue; - // 2. 初始化时间戳 (防止新进程为0) - if (pStats.lastForegroundTime.QuadPart == 0) - { + // 初始化时间戳 + if (pStats.lastForegroundTime.QuadPart == 0) { pStats.lastForegroundTime = now; continue; } - // 3. 检查后台超时 + // 计算后台时间 if (now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; + double secondsInBg = (double)timeInBg / 10000000.0; + + // [调试] 如果后台时间超过阈值的一半,打印日志观察 + + if (secondsInBg > (settings.cpuSetResetInterval / 2.0)) { + LogColor(COLOR_DEFAULT, "[调试] 进程 %lu 已后台 %.1f 秒 (阈值 %d)\n", pid, secondsInBg, settings.cpuSetResetInterval); + } + if (timeInBg > resetThreshold) { - // 触发超时,先输出诊断信息 - LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %llu 秒 (阈值 %d),正在检查线程状态...\n", pid, timeInBg / 10000000, settings.cpuSetResetInterval); + if (!pSetThreadSelectedCpuSets) { + LogColor(COLOR_ERROR, "[错误] 触发清理但 API 不可用。\n"); + continue; + } bool triggeredReset = false; int resetCount = 0; + int threadsChecked = 0; for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; + threadsChecked++; if (tStats.hasCpuSets) { @@ -956,15 +986,15 @@ void ThreadOptimizerThread() HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION, FALSE, tStats.threadId); if (hThread) { - // 清空 CPU Sets 和 理想核心 BOOL b1 = pSetThreadSelectedCpuSets(hThread, NULL, 0); - DWORD d2 = SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); - + SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); if (b1) resetCount++; CloseHandle(hThread); } + else { + LogColor(COLOR_WARNING, "[警告] 无法打开线程 %lu 进行重置。\n", tStats.threadId); + } - // 清除标记 tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } @@ -972,16 +1002,17 @@ void ThreadOptimizerThread() if (triggeredReset) { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台超过 %d 秒,已重置 %d 个线程的 CPU Sets。\n", - pid, settings.cpuSetResetInterval, resetCount); + LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台 %.1f 秒,重置了 %d 个线程 (共扫描 %d 个)。\n", + pid, secondsInBg, resetCount, threadsChecked); } else { - // 如果没有线程需要重置,也记录一下,证明逻辑跑通了 - LogColor(COLOR_DEFAULT, " -> [诊断] 进程 %lu 无需重置 (未设置 CPU Sets)。\n", pid); + // [关键] 即使没有线程被重置,也输出日志,证明逻辑到了这里 + // 这说明进程超时了,但没有线程被标记为 hasCpuSets + LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %.1f 秒,但没有标记为 hasCpuSets 的线程。\n", pid, secondsInBg); } - // 更新时间戳,避免下一秒重复检查 + // 更新时间戳,避免刷屏 pStats.lastForegroundTime = now; } } @@ -1048,7 +1079,7 @@ void ThreadOptimizerThread() ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; - // 再次更新前台时间 (双重保险) + // 再次更新前台时间 procStats.lastForegroundTime = now; // --- 检测前台切换 --- From 0a9491c0b82e7965abc706c4cdf6d3f7b840347e Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 01:57:06 +0800 Subject: [PATCH 19/23] Add files via upload --- ForegroundBooster.cpp | 155 ++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 105 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index d3066d6..ca5d99a 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -265,7 +265,7 @@ void ParseIniFile(const std::wstring& path) else if (key == L"IdealCore") settings.idealCore = std::stoi(value); else if (key == L"CpuSetInterval") settings.cpuSetInterval = std::stoi(value); else if (key == L"OptimizeOtherThreads") settings.optimizeOtherThreads = (std::stoi(value) != 0); - else if (key == L"CpuSetResetInterval") settings.optimizeOtherThreads = (std::stoi(value) != 0); + else if (key == L"CpuSetResetInterval") settings.cpuSetResetInterval = std::stoi(value); } } else if (currentSection == L"BlackList") @@ -871,27 +871,22 @@ void ThreadOptimizerThread() HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); HMODULE hNtdll = GetModuleHandleA("ntdll.dll"); - SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = + SetThreadSelectedCpuSetsPtr pSetThreadSelectedCpuSets = (SetThreadSelectedCpuSetsPtr)GetProcAddress(hKernel32, "SetThreadSelectedCpuSets"); - GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = + GetSystemCpuSetInformationPtr pGetSystemCpuSetInformation = (GetSystemCpuSetInformationPtr)GetProcAddress(hKernel32, "GetSystemCpuSetInformation"); - GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = + GetProcessDefaultCpuSetsPtr pGetProcessDefaultCpuSets = (GetProcessDefaultCpuSetsPtr)GetProcAddress(hKernel32, "GetProcessDefaultCpuSets"); - NtQueryInformationThreadPtr pNtQueryInformationThread = + NtQueryInformationThreadPtr pNtQueryInformationThread = (NtQueryInformationThreadPtr)GetProcAddress(hNtdll, "NtQueryInformationThread"); - // --- [调试] 启动自检 --- - LogColor(COLOR_INFO, "[调试] 优化线程启动。\n"); - LogColor(COLOR_INFO, "[调试] API SetThreadSelectedCpuSets: %p\n", pSetThreadSelectedCpuSets); - LogColor(COLOR_INFO, "[调试] 配置 CpuSetResetInterval: %d\n", settings.cpuSetResetInterval); - if (!pSetThreadSelectedCpuSets || !pGetSystemCpuSetInformation) { - LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+)。\n"); + LogColor(COLOR_WARNING, "[警告] 当前系统不支持 CPU Sets API (需要 Win10 1709+) 优化功能受限\n"); } - ULONG idealCoreCpuSetId = 0; - ULONG mainThreadFallbackCpuSetId = 0; + ULONG idealCoreCpuSetId = 0; + ULONG mainThreadFallbackCpuSetId = 0; if (settings.idealCore >= 0 && pGetSystemCpuSetInformation) { idealCoreCpuSetId = GetCpuSetIdFromLogicalIndex((DWORD)settings.idealCore, pGetSystemCpuSetInformation); @@ -901,8 +896,7 @@ void ThreadOptimizerThread() } CpuTopology topology; - DWORD previousPid = 0; - int debugLogCounter = 0; // 用于控制调试日志频率 + DWORD previousPid = 0; while (true) { @@ -910,115 +904,62 @@ void ThreadOptimizerThread() DWORD currentPid = lastProcessId; + // --- 修正点 1: 在循环顶部统一定义时间变量 --- FILETIME ftSystem; GetSystemTimeAsFileTime(&ftSystem); ULARGE_INTEGER now = FT2ULL(ftSystem); + // ------------------------------------------- - // --- 1. 优先更新当前前台进程的时间戳 --- - if (currentPid != 0) - { - std::lock_guard lock(g_statsMutex); - // 如果缓存中还没有这个进程,这里不会插入,会在下面的优化逻辑中插入 - // 但如果有了,必须立即更新,防止被误杀 - if (g_processStatsCache.count(currentPid)) { - g_processStatsCache[currentPid].lastForegroundTime = now; - } - } - - // --- 2. 后台进程清理逻辑 --- - // 移除 pSetThreadSelectedCpuSets 检查,即使 API 不存在也输出日志以便调试 - if (settings.cpuSetResetInterval > 0) + // --- 后台进程清理逻辑 --- + if (settings.cpuSetResetInterval > 0 && pSetThreadSelectedCpuSets) { std::lock_guard lock(g_statsMutex); ULONGLONG resetThreshold = (ULONGLONG)settings.cpuSetResetInterval * 10000000ULL; - // [调试] 每5秒输出一次缓存状态 - if (++debugLogCounter % 5 == 0) { - LogColor(COLOR_DEFAULT, "[调试] 正在检查后台清理... 缓存进程数: %zu, 当前前台: %lu\n", g_processStatsCache.size(), currentPid); - } - for (auto& procPair : g_processStatsCache) { DWORD pid = procPair.first; ProcessStats& pStats = procPair.second; - // 跳过当前前台进程 - if (pid == currentPid) continue; - - // 初始化时间戳 - if (pStats.lastForegroundTime.QuadPart == 0) { + if (pid == currentPid) + { pStats.lastForegroundTime = now; continue; } - // 计算后台时间 - if (now.QuadPart > pStats.lastForegroundTime.QuadPart) + if (pStats.lastForegroundTime.QuadPart > 0 && now.QuadPart > pStats.lastForegroundTime.QuadPart) { ULONGLONG timeInBg = now.QuadPart - pStats.lastForegroundTime.QuadPart; - double secondsInBg = (double)timeInBg / 10000000.0; - - // [调试] 如果后台时间超过阈值的一半,打印日志观察 - - if (secondsInBg > (settings.cpuSetResetInterval / 2.0)) { - LogColor(COLOR_DEFAULT, "[调试] 进程 %lu 已后台 %.1f 秒 (阈值 %d)\n", pid, secondsInBg, settings.cpuSetResetInterval); - } - if (timeInBg > resetThreshold) { - if (!pSetThreadSelectedCpuSets) { - LogColor(COLOR_ERROR, "[错误] 触发清理但 API 不可用。\n"); - continue; - } - - bool triggeredReset = false; - int resetCount = 0; - int threadsChecked = 0; - + bool anyReset = false; for (auto& threadPair : pStats.threads) { ThreadStats& tStats = threadPair.second; - threadsChecked++; - if (tStats.hasCpuSets) { - triggeredReset = true; - HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION | THREAD_SET_INFORMATION, FALSE, tStats.threadId); + HANDLE hThread = OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, tStats.threadId); if (hThread) { - BOOL b1 = pSetThreadSelectedCpuSets(hThread, NULL, 0); - SetThreadIdealProcessor(hThread, MAXIMUM_PROCESSORS); - if (b1) resetCount++; + if (pSetThreadSelectedCpuSets(hThread, NULL, 0)) anyReset = true; CloseHandle(hThread); } - else { - LogColor(COLOR_WARNING, "[警告] 无法打开线程 %lu 进行重置。\n", tStats.threadId); - } - tStats.hasCpuSets = false; tStats.assignedCpuSetId = 0; } } - if (triggeredReset) - { - LogColor(COLOR_WARNING, "[清理] 进程 %lu 已在后台 %.1f 秒,重置了 %d 个线程 (共扫描 %d 个)。\n", - pid, secondsInBg, resetCount, threadsChecked); - } - else + if (anyReset) { - // [关键] 即使没有线程被重置,也输出日志,证明逻辑到了这里 - // 这说明进程超时了,但没有线程被标记为 hasCpuSets - LogColor(COLOR_INFO, "[诊断] 进程 %lu 已后台 %.1f 秒,但没有标记为 hasCpuSets 的线程。\n", pid, secondsInBg); + LogColor(COLOR_WARNING, "[清理] 进程 %lu 在后台超过 %d 秒 重置其线程 CPU Sets\n", + pid, settings.cpuSetResetInterval); + pStats.lastForegroundTime = now; } - - // 更新时间戳,避免刷屏 - pStats.lastForegroundTime = now; } } } } - // ------------------------------------ if (currentPid == 0) continue; @@ -1057,7 +998,7 @@ void ThreadOptimizerThread() { procStats.ignoreMonitoring = true; procStats.threads.clear(); - LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 设置了自定义亲和性或 CPU Sets,停止追踪其线程负载。\n", currentPid); + LogColor(COLOR_WARNING, " -> [监控停止] 进程 %lu 已设置亲和性或 CPU Sets 停止追踪其线程负载\n", currentPid); } continue; } @@ -1067,6 +1008,10 @@ void ThreadOptimizerThread() AnalyzeCpuTopology(pGetSystemCpuSetInformation, topology); } + // --- 修正点 2: 删除了此处重复定义的 ftSystem 和 now --- + // (原代码这里有重复定义 导致编译错误) + // --------------------------------------------------- + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot == INVALID_HANDLE_VALUE) continue; @@ -1078,8 +1023,8 @@ void ThreadOptimizerThread() std::lock_guard lock(g_statsMutex); ProcessStats& procStats = g_processStatsCache[currentPid]; procStats.processId = currentPid; - - // 再次更新前台时间 + + // 再次更新前台时间 防止清理逻辑误判 (双重保险) procStats.lastForegroundTime = now; // --- 检测前台切换 --- @@ -1087,12 +1032,12 @@ void ThreadOptimizerThread() { if (procStats.lastOptimizationTime.QuadPart == 0) { - LogColor(COLOR_INFO, "[监控] 新进程 %lu (无缓存),将立即执行首次优化 (仅主线程)。\n", currentPid); + LogColor(COLOR_INFO, "[监控] 新进程 %lu 将立即执行首次优化\n", currentPid); } else { - LogColor(COLOR_INFO, "[监控] 旧进程 %lu (有缓存),将在 %d 秒后应用优化。\n", currentPid, settings.cpuSetInterval); - procStats.lastOptimizationTime = now; + LogColor(COLOR_INFO, "[监控] 旧进程 %lu 将在 %d 秒后应用优化\n", currentPid, settings.cpuSetInterval); + procStats.lastOptimizationTime = now; for (auto& pair : procStats.threads) { pair.second.intervalStartTime = now; pair.second.intervalStartKernelTime = pair.second.lastKernelTime; @@ -1113,14 +1058,14 @@ void ThreadOptimizerThread() currentThreadIds.push_back(tid); bool isNewThread = (procStats.threads.find(tid) == procStats.threads.end()); - + if (isNewThread) { ThreadStats ts = {}; ts.threadId = tid; ts.hasCpuSets = false; ts.assignedCpuSetId = 0; - + HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, tid); if (hThread) { @@ -1150,8 +1095,8 @@ void ThreadOptimizerThread() ts.lastKernelTime = FT2ULL(ftKernel); ts.lastUserTime = FT2ULL(ftUser); ts.lastCheckTime = now; - - if (procStats.lastOptimizationTime.QuadPart != 0 && + + if (procStats.lastOptimizationTime.QuadPart != 0 && ts.intervalStartTime.QuadPart != procStats.lastOptimizationTime.QuadPart) { ts.intervalStartKernelTime = ts.lastKernelTime; @@ -1183,9 +1128,9 @@ void ThreadOptimizerThread() { bool isImmediateRun = (procStats.lastOptimizationTime.QuadPart == 0); if (isImmediateRun) { - LogColor(COLOR_INFO, "[分析] 触发新进程立即优化 (仅设置主线程)...\n"); + LogColor(COLOR_INFO, "[分析] 触发新进程立即优化...\n"); } else { - LogColor(COLOR_INFO, "[分析] 观察周期结束,正在计算平均负载并应用优化...\n"); + LogColor(COLOR_INFO, "[分析] 观察周期结束 正在计算平均负载并应用优化...\n"); } for (auto& pair : procStats.threads) @@ -1196,7 +1141,7 @@ void ThreadOptimizerThread() continue; } ULONGLONG timeDelta = now.QuadPart - ts.intervalStartTime.QuadPart; - ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + + ULONGLONG workDelta = (ts.lastKernelTime.QuadPart - ts.intervalStartKernelTime.QuadPart) + (ts.lastUserTime.QuadPart - ts.intervalStartUserTime.QuadPart); if (timeDelta > 0) ts.intervalAverageLoad = (double)workDelta / (double)timeDelta * 100.0; else ts.intervalAverageLoad = 0.0; @@ -1216,7 +1161,7 @@ void ThreadOptimizerThread() if (pMainThread == nullptr || CompareFileTime(&t.creationTime, &pMainThread->creationTime) < 0) pMainThread = &t; } - + if (!isImmediateRun) { for (auto& pair : procStats.threads) @@ -1252,7 +1197,7 @@ void ThreadOptimizerThread() if (pHeavyThread && pHeavyThread->intervalAverageLoad > 10.0) { - LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%),执行分离策略。\n", + LogColor(COLOR_INFO, " -> 检测到重负载线程 %lu (平均负载 %.1f%%) 执行分离策略\n", pHeavyThread->threadId, pHeavyThread->intervalAverageLoad); if (!pHeavyThread->hasCpuSets || pHeavyThread->assignedCpuSetId != idealCoreCpuSetId) @@ -1276,7 +1221,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hHeavy, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu。\n", pHeavyThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 线程 %lu (重负载) 绑定 CPU Set ID: %lu\n", pHeavyThread->threadId, idealCoreCpuSetId); pHeavyThread->hasCpuSets = true; pHeavyThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1293,7 +1238,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { mainThreadFallbackCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)。\n", + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu (Core %d)\n", pMainThread->threadId, mainThreadFallbackCpuSetId, settings.idealCore - 2); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = mainThreadFallbackCpuSetId; @@ -1327,7 +1272,7 @@ void ThreadOptimizerThread() ULONG cpuSetIds[] = { idealCoreCpuSetId }; if (pSetThreadSelectedCpuSets(hMain, cpuSetIds, 1)) { - LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu。\n", pMainThread->threadId, idealCoreCpuSetId); + LogColor(COLOR_SUCCESS, " -> [优化] 主线程 %lu 绑定 CPU Set ID: %lu\n", pMainThread->threadId, idealCoreCpuSetId); pMainThread->hasCpuSets = true; pMainThread->assignedCpuSetId = idealCoreCpuSetId; } @@ -1374,7 +1319,7 @@ void ThreadOptimizerThread() std::sort(htQueue.rbegin(), htQueue.rend()); allocationQueue.insert(allocationQueue.end(), htQueue.begin(), htQueue.end()); - + if (mainHT != -1) allocationQueue.push_back(mainHT); if (heavyHT != -1 && heavyHT != mainHT) allocationQueue.push_back(heavyHT); @@ -1385,7 +1330,7 @@ void ThreadOptimizerThread() LogColor(COLOR_INFO, " -> [其余线程] 正在为 %zu 个线程分配理想核心 (队列长度: %zu)...\n", otherThreads.size(), allocationQueue.size()); int successCount = 0; for (size_t i = 0; i < otherThreads.size(); ++i) { - DWORD targetCore = allocationQueue[i % allocationQueue.size()]; + DWORD targetCore = allocationQueue[i % allocationQueue.size()]; HANDLE hThread = OpenThread(THREAD_SET_INFORMATION, FALSE, otherThreads[i]->threadId); if (hThread) { if (SetThreadIdealProcessor(hThread, targetCore) != (DWORD)-1) { @@ -1394,14 +1339,14 @@ void ThreadOptimizerThread() CloseHandle(hThread); } } - LogColor(COLOR_SUCCESS, " -> 成功设置了 %d / %zu 个线程的理想核心。\n", successCount, otherThreads.size()); + LogColor(COLOR_SUCCESS, " -> 已设置 %d / %zu 个线程的理想核心\n", successCount, otherThreads.size()); } } } } } - } - + } + CloseHandle(hSnapshot); } } From ace5d3637e106cd94be2ac53ad3893f204da9b8c Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:16:42 +0800 Subject: [PATCH 20/23] Add files via upload --- ForegroundBooster.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index ca5d99a..50a2f69 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -107,7 +107,7 @@ struct Settings int dscp = -1; int scheduling = -1; int weight = -1; - int processListInterval = 60; + int ioResetInterval = 60; int idealCore = -1; int cpuSetInterval = 600; bool optimizeOtherThreads = false; @@ -261,7 +261,7 @@ void ParseIniFile(const std::wstring& path) else if (key == L"DSCP") settings.dscp = std::stoi(value); else if (key == L"Scheduling") settings.scheduling = std::stoi(value); else if (key == L"Weight") settings.weight = std::stoi(value); - else if (key == L"ProcessList") settings.processListInterval = std::stoi(value); + else if (key == L"IOReset") settings.ioResetInterval = std::stoi(value); else if (key == L"IdealCore") settings.idealCore = std::stoi(value); else if (key == L"CpuSetInterval") settings.cpuSetInterval = std::stoi(value); else if (key == L"OptimizeOtherThreads") settings.optimizeOtherThreads = (std::stoi(value) != 0); @@ -902,6 +902,15 @@ void ThreadOptimizerThread() { std::this_thread::sleep_for(std::chrono::seconds(1)); + // --- 新增:主开关检查 --- + // 如果未设置 IdealCore 则视为禁用所有 CPU 优化功能 + // 跳过后续的拓扑分析、监控、日志和计算 仅保持线程存活 + if (settings.idealCore < 0) + { + continue; + } + // ----------------------- + DWORD currentPid = lastProcessId; // --- 修正点 1: 在循环顶部统一定义时间变量 --- @@ -1355,7 +1364,7 @@ void ProcessListCheckThread() { while (true) { - std::this_thread::sleep_for(std::chrono::seconds(settings.processListInterval)); + std::this_thread::sleep_for(std::chrono::seconds(settings.ioResetInterval)); // 检查前台是否发生变化 if (g_foregroundHasChanged.exchange(false)) From 90529d69154a2970b63ec3bdd46514e080369884 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:37:53 +0800 Subject: [PATCH 21/23] Add files via upload --- ForegroundBooster.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ForegroundBooster.cpp b/ForegroundBooster.cpp index 50a2f69..17e76a3 100644 --- a/ForegroundBooster.cpp +++ b/ForegroundBooster.cpp @@ -972,6 +972,38 @@ void ThreadOptimizerThread() if (currentPid == 0) continue; + // --- 新增:黑名单检查 (带缓存) --- + static DWORD lastCheckedBlacklistPid = 0; + static bool isBlacklisted = false; + + if (currentPid != lastCheckedBlacklistPid) + { + std::wstring name = GetProcessNameById(currentPid); + // 转换为小写并检查是否在黑名单中 + if (blackList.count(to_lower(name))) + { + isBlacklisted = true; + LogColor(COLOR_WARNING, "[监控] 进程 %lu (%ws) 在黑名单中 跳过 CPU 优化\n", currentPid, name.c_str()); + + // 如果缓存中有该进程的数据 清除它 + std::lock_guard lock(g_statsMutex); + if (g_processStatsCache.count(currentPid)) + { + g_processStatsCache.erase(currentPid); + } + } + else + { + isBlacklisted = false; + } + lastCheckedBlacklistPid = currentPid; + } + + if (isBlacklisted) + { + continue; // 直接跳过后续所有逻辑 (快照、计算、优化) + } + // --- 快速检查:是否忽略 --- { std::lock_guard lock(g_statsMutex); From 98c224572bc6d80d166341320fe58035d980a9d8 Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:43:56 +0800 Subject: [PATCH 22/23] Add files via upload --- ForegroundBooster.ini | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/ForegroundBooster.ini b/ForegroundBooster.ini index f7b11c5..7f6012a 100644 --- a/ForegroundBooster.ini +++ b/ForegroundBooster.ini @@ -1,6 +1,15 @@ [Settings] -;主线程理想核心 -IdealCore=2 +;理想核心 +IdealCore=6 + +;CPU集合‌设置间隔 +CpuSetInterval=300 + +;后台CPU集合‌重置间隔 +CpuSetResetInterval=300 + +;其他线程设置理想核心 +OptimizeOtherThreads=1 ;调度优先级 ;值:0-9 @@ -14,10 +23,10 @@ IdealCore=2 ;值:0-63 ;DSCP=46 -;进程列表检测间隔 -ProcessList=60 +;I/O优先级重置间隔 +IOReset=60 -;DWM-MMCSS应用间隔 +;DWM应用MMCSS间隔 DwmEnableMMCSS=60 [WhiteList] From 52de78d5d4a349338e87c1148555df6d16da63db Mon Sep 17 00:00:00 2001 From: signin404 <145902543+signin404@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:46:21 +0800 Subject: [PATCH 23/23] Add files via upload --- ps1/ThreadCpuSetsCheck.ps1 | 242 +++++++++++++++++++++++++++++++++++++ ps1/ThreadCpuSetsSet.ps1 | 204 +++++++++++++++++++++++++++++++ 2 files changed, 446 insertions(+) create mode 100644 ps1/ThreadCpuSetsCheck.ps1 create mode 100644 ps1/ThreadCpuSetsSet.ps1 diff --git a/ps1/ThreadCpuSetsCheck.ps1 b/ps1/ThreadCpuSetsCheck.ps1 new file mode 100644 index 0000000..9b0efd6 --- /dev/null +++ b/ps1/ThreadCpuSetsCheck.ps1 @@ -0,0 +1,242 @@ +<# +.SYNOPSIS + ¼à¿Øָ¶¨Ï̵߳ÄCPU SetsÅäÖà +.DESCRIPTION + ÿÃëѭ»·¼ì²鲢ÏÔʾָ¶¨Ï߳ÌIDµĵ±ǰCPU SetsÅäÖà +.PARAMETER id + Ï߳ÌID +.EXAMPLE + .\ThreadCpuSetsCheck.ps1 -id 1234 +#> + +param( + [Parameter(Mandatory=$true)] + [int]$id +) + +# ¶¨ÒåWindows APIºͽṹ +Add-Type @" +using System; +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Sequential)] +public struct SYSTEM_CPU_SET_INFORMATION { + public uint Size; + public uint Type; + public uint Id; + public ushort Group; + public byte LogicalProcessorIndex; + public byte CoreIndex; + public byte LastLevelCacheIndex; + public byte NumaNodeIndex; + public byte EfficiencyClass; + public byte AllFlags; + public uint Reserved; + public ulong AllocationTag; +} + +public class ThreadCpuSets { + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetThreadSelectedCpuSets( + IntPtr Thread, + uint[] CpuSetIds, + uint CpuSetIdCount, + out uint ReturnedIdCount + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetSystemCpuSetInformation( + IntPtr Information, + uint BufferLength, + out uint ReturnLength, + IntPtr Process, + uint Flags + ); + + public const uint THREAD_QUERY_LIMITED_INFORMATION = 0x0800; +} +"@ + +function Get-CpuSetMapping { + try { + # »ñȡϵͳCPU SetÐÅϢ + $bufferSize = [System.UInt32]4096 + $buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($bufferSize) + $returnLength = [System.UInt32]0 + + $result = [ThreadCpuSets]::GetSystemCpuSetInformation( + $buffer, + $bufferSize, + [ref]$returnLength, + [IntPtr]::Zero, + 0 + ) + + if (-not $result) { + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer) + return $null + } + + # ½âÎöCPU SetÐÅϢ + $cpuSetList = @() + $offset = 0 + + while ($offset -lt $returnLength) { + $cpuSetInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure( + [IntPtr]::Add($buffer, $offset), + [type][SYSTEM_CPU_SET_INFORMATION] + ) + + if ($cpuSetInfo.Type -eq 0) { + $cpuSetList += [PSCustomObject]@{ + LogicalProcessor = [int]$cpuSetInfo.LogicalProcessorIndex + CpuSetId = [int]$cpuSetInfo.Id + } + } + + $offset += $cpuSetInfo.Size + } + + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer) + return $cpuSetList + + } catch { + return $null + } +} + +function Get-ThreadCpuSets { + param([int]$ThreadId, [array]$CpuSetMapping) + + try { + # ´ò¿ªÏ߳̾ä±ú + $threadHandle = [ThreadCpuSets]::OpenThread( + [ThreadCpuSets]::THREAD_QUERY_LIMITED_INFORMATION, + $false, + [System.UInt32]$ThreadId + ) + + if ($threadHandle -eq [IntPtr]::Zero) { + return $null + } + + # »ñȡCPU Sets + $returnedIds = New-Object System.UInt32[] 64 + $returnedCount = [System.UInt32]0 + + $result = [ThreadCpuSets]::GetThreadSelectedCpuSets( + $threadHandle, + $returnedIds, + [System.UInt32]64, + [ref]$returnedCount + ) + + [ThreadCpuSets]::CloseHandle($threadHandle) + + if (-not $result) { + return $null + } + + # ¹¹½¨·µ»ØÊý¾Ý + $cpuSets = @() + for ($i = 0; $i -lt $returnedCount; $i++) { + $setCpuSetId = [int]$returnedIds[$i] + $cpuInfo = $CpuSetMapping | Where-Object { $_.CpuSetId -eq $setCpuSetId } + + $cpuSets += [PSCustomObject]@{ + CpuSetId = $setCpuSetId + LogicalProcessor = if ($cpuInfo) { $cpuInfo.LogicalProcessor } else { "δ֪" } + } + } + + return $cpuSets + + } catch { + return $null + } +} + +# Ö÷ѭ»· +Write-Host "=====================================" -ForegroundColor Cyan +Write-Host "Ï߳ÌCPU Sets¼à¿ØÆ÷" -ForegroundColor Cyan +Write-Host "¼à¿ØÏ߳ÌID: $id" -ForegroundColor Yellow +Write-Host "°´ Ctrl+C Í˳ö" -ForegroundColor Gray +Write-Host "=====================================" -ForegroundColor Cyan +Write-Host "" + +# »ñȡCPU SetӳÉä±í£¨ֻÐèҪ»ñȡһ´Σ© +Write-Host "ÕýÔڼÓÔØCPU SetsӳÉä±í..." -ForegroundColor Gray +$cpuSetMapping = Get-CpuSetMapping + +if ($null -eq $cpuSetMapping) { + Write-Host "´íÎó: Î޷¨»ñȡϵͳCPU SetsÐÅϢ" -ForegroundColor Red + exit 1 +} + +Write-Host "ϵͳ¹²ÓÐ $($cpuSetMapping.Count) ¸öÂ߼­´¦ÀíÆ÷`n" -ForegroundColor Gray + +$iteration = 0 +$lastCpuSets = $null + +try { + while ($true) { + $iteration++ + $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + + # »ñȡµ±ǰCPU Sets + $currentCpuSets = Get-ThreadCpuSets -ThreadId $id -CpuSetMapping $cpuSetMapping + + if ($null -eq $currentCpuSets) { + Write-Host "[$timestamp] " -NoNewline -ForegroundColor Gray + Write-Host "Ï߳Ì $id ²»´æÔڻòÎ޷¨·ÃÎÊ" -ForegroundColor Red + } + elseif ($currentCpuSets.Count -eq 0) { + Write-Host "[$timestamp] " -NoNewline -ForegroundColor Gray + Write-Host "Ï߳Ì $id - CPU Sets: " -NoNewline -ForegroundColor White + Write-Host "δÉèÖà (ʹÓÃËùÓÐCPU)" -ForegroundColor Yellow + } + else { + # ¼ì²éÊǷñÓб仯 + $currentString = ($currentCpuSets | ForEach-Object { "$($_.CpuSetId)" }) -join "," + $hasChanged = $false + + if ($null -ne $lastCpuSets) { + $lastString = ($lastCpuSets | ForEach-Object { "$($_.CpuSetId)" }) -join "," + $hasChanged = ($currentString -ne $lastString) + } + + Write-Host "[$timestamp] " -NoNewline -ForegroundColor Gray + Write-Host "Ï߳Ì $id - CPU Sets: " -NoNewline -ForegroundColor White + + $cpuSetDisplay = @() + foreach ($cpuSet in $currentCpuSets) { + $cpuSetDisplay += "CPU$($cpuSet.LogicalProcessor) (ID:$($cpuSet.CpuSetId))" + } + + if ($hasChanged) { + Write-Host ($cpuSetDisplay -join ", ") -ForegroundColor Green + Write-Host " *** ÅäÖÃÒѱ仯 ***" -ForegroundColor Magenta + } else { + Write-Host ($cpuSetDisplay -join ", ") -ForegroundColor Cyan + } + + $lastCpuSets = $currentCpuSets + } + + # ÿ10´εü´úÏÔʾһ¸ö·ָôÏß + if ($iteration % 10 -eq 0) { + Write-Host ("-" * 80) -ForegroundColor DarkGray + } + + Start-Sleep -Seconds 1 + } +} +catch { + Write-Host "`n`n³ÌÐòÒÑÖÕֹ" -ForegroundColor Yellow +} \ No newline at end of file diff --git a/ps1/ThreadCpuSetsSet.ps1 b/ps1/ThreadCpuSetsSet.ps1 new file mode 100644 index 0000000..a6427e7 --- /dev/null +++ b/ps1/ThreadCpuSetsSet.ps1 @@ -0,0 +1,204 @@ +<# +.SYNOPSIS + ÉèÖÃָ¶¨Ï̵߳ÄCPU Sets +.DESCRIPTION + ´˽ű¾ÓÃÓÚÉèÖÃָ¶¨Ï߳ÌIDµÄCPU Sets ʹÓÃWindows APIʵÏÖ +.PARAMETER id + Ï߳ÌID +.PARAMETER c + CPU±àºţ¨´Ó0¿ªʼµÄÂ߼­´¦ÀíÆ÷±àºţ© +.EXAMPLE + .\ThreadCpuSetsSet.ps1 -id 1234 -c 8 +#> + +param( + [Parameter(Mandatory=$true)] + [int]$id, + + [Parameter(Mandatory=$true)] + [int]$c +) + +# ¶¨ÒåWindows APIºͽṹ +Add-Type @" +using System; +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Sequential)] +public struct SYSTEM_CPU_SET_INFORMATION { + public uint Size; + public uint Type; + public uint Id; + public ushort Group; + public byte LogicalProcessorIndex; + public byte CoreIndex; + public byte LastLevelCacheIndex; + public byte NumaNodeIndex; + public byte EfficiencyClass; + public byte AllFlags; + public uint Reserved; + public ulong AllocationTag; +} + +public class ThreadCpuSets { + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool SetThreadSelectedCpuSets( + IntPtr Thread, + uint[] CpuSetIds, + uint CpuSetIdCount + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetThreadSelectedCpuSets( + IntPtr Thread, + uint[] CpuSetIds, + uint CpuSetIdCount, + out uint ReturnedIdCount + ); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool GetSystemCpuSetInformation( + IntPtr Information, + uint BufferLength, + out uint ReturnLength, + IntPtr Process, + uint Flags + ); + + public const uint THREAD_SET_LIMITED_INFORMATION = 0x0400; + public const uint THREAD_QUERY_LIMITED_INFORMATION = 0x0800; +} +"@ + +try { + Write-Host "ÕýÔڻñȡϵͳCPU SetsÐÅϢ..." -ForegroundColor Cyan + + # »ñȡϵͳCPU SetÐÅϢ + $bufferSize = [System.UInt32]4096 + $buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($bufferSize) + $returnLength = [System.UInt32]0 + + $result = [ThreadCpuSets]::GetSystemCpuSetInformation( + $buffer, + $bufferSize, + [ref]$returnLength, + [IntPtr]::Zero, + 0 + ) + + if (-not $result) { + $errorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer) + throw "Î޷¨»ñȡCPU SetsÐÅϢ´íÎó´úÂë: $errorCode" + } + + # ½âÎöCPU SetÐÅϢ - ʹÓÃÊý×é¶ø²»Êǹþϣ±í + $cpuSetList = @() + $offset = 0 + $structSize = [System.Runtime.InteropServices.Marshal]::SizeOf([type][SYSTEM_CPU_SET_INFORMATION]) + + while ($offset -lt $returnLength) { + $cpuSetInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure( + [IntPtr]::Add($buffer, $offset), + [type][SYSTEM_CPU_SET_INFORMATION] + ) + + if ($cpuSetInfo.Type -eq 0) { # CpuSetInformation type + $logicalProc = [int]$cpuSetInfo.LogicalProcessorIndex + $cpuSetId = [int]$cpuSetInfo.Id + + $cpuSetList += [PSCustomObject]@{ + LogicalProcessor = $logicalProc + CpuSetId = $cpuSetId + } + + Write-Host " Â߼­´¦ÀíÆ÷ $logicalProc -> CPU Set ID $cpuSetId" -ForegroundColor Gray + } + + $offset += $cpuSetInfo.Size + } + + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer) + + # ²éÕÒָ¶¨µÄÂ߼­´¦ÀíÆ÷ + $targetCpuSet = $cpuSetList | Where-Object { $_.LogicalProcessor -eq $c } + + if ($null -eq $targetCpuSet) { + $maxCpu = ($cpuSetList | Measure-Object -Property LogicalProcessor -Maximum).Maximum + throw "Â߼­´¦ÀíÆ÷ $c ²»´æÔڿÉÓ÷¶Χ: 0-$maxCpu" + } + + $targetCpuSetId = $targetCpuSet.CpuSetId + Write-Host "`nÂ߼­´¦ÀíÆ÷ $c ¶ÔӦµÄCPU Set ID: $targetCpuSetId" -ForegroundColor Yellow + Write-Host "ÕýÔÚÉèÖÃÏ߳Ì $id µÄCPU Sets..." -ForegroundColor Cyan + + # ´ò¿ªÏ߳̾ä±ú + $threadHandle = [ThreadCpuSets]::OpenThread( + [ThreadCpuSets]::THREAD_SET_LIMITED_INFORMATION -bor [ThreadCpuSets]::THREAD_QUERY_LIMITED_INFORMATION, + $false, + [System.UInt32]$id + ) + + if ($threadHandle -eq [IntPtr]::Zero) { + $errorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() + throw "Î޷¨´ò¿ªÏ߳Ì $id´íÎó´úÂë: $errorCodeÇëȷÈÏÏ߳ÌIDÊǷñÕýȷÇÒÓÐ×㹻ȨÏÞ" + } + + Write-Host "³ɹ¦´ò¿ªÏ߳̾ä±ú" -ForegroundColor Green + + # ÉèÖÃCPU Sets - ʹÓÃÕýȷµÄCPU Set ID + $cpuSetIds = New-Object System.UInt32[] 1 + $cpuSetIds[0] = [System.UInt32]$targetCpuSetId + + $result = [ThreadCpuSets]::SetThreadSelectedCpuSets( + $threadHandle, + $cpuSetIds, + [System.UInt32]1 + ) + + if (-not $result) { + $errorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() + [ThreadCpuSets]::CloseHandle($threadHandle) + throw "ÉèÖÃCPU Setsʧ°ܴíÎó´úÂë: $errorCode" + } + + Write-Host "? ³ɹ¦½«Ï߳Ì $id µÄCPU SetsÉèÖÃΪÂ߼­´¦ÀíÆ÷ $c (CPU Set ID: $targetCpuSetId)" -ForegroundColor Green + + # Ñé֤ÉèÖà + $returnedIds = New-Object System.UInt32[] 64 + $returnedCount = [System.UInt32]0 + + $verifyResult = [ThreadCpuSets]::GetThreadSelectedCpuSets( + $threadHandle, + $returnedIds, + [System.UInt32]64, + [ref]$returnedCount + ) + + if ($verifyResult -and $returnedCount -gt 0) { + Write-Host "`nµ±ǰÏ̵߳ÄCPU SetsÅäÖÃ:" -ForegroundColor Yellow + for ($i = 0; $i -lt $returnedCount; $i++) { + $setCpuSetId = $returnedIds[$i] + # ·´Ïò²éÕҶÔӦµÄÂ߼­´¦ÀíÆ÷ + $cpuInfo = $cpuSetList | Where-Object { $_.CpuSetId -eq $setCpuSetId } + if ($cpuInfo) { + Write-Host " CPU Set ID: $setCpuSetId (Â߼­´¦ÀíÆ÷: $($cpuInfo.LogicalProcessor))" -ForegroundColor White + } else { + Write-Host " CPU Set ID: $setCpuSetId" -ForegroundColor White + } + } + } + + # ¹رվä±ú + [void][ThreadCpuSets]::CloseHandle($threadHandle) + +} catch { + Write-Host "´íÎó: $_" -ForegroundColor Red + exit 1 +} \ No newline at end of file