如何限制Windows上进程的CPU使用率? (需要代码,而不是应用程序) [英] How do you limit a process' CPU usage on Windows? (need code, not an app)

查看:827
本文介绍了如何限制Windows上进程的CPU使用率? (需要代码,而不是应用程序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有些程序可以限制Windows中进程的CPU使用率。例如 BES ThreadMaster 。我需要编写自己的程序,这些程序具有与这些程序相同的功能,但是具有不同的配置功能。有人知道如何对进程进行CPU节流(代码)吗?我不是在谈论设置进程的优先级,而是如何将其CPU使用率限制为例如15%,即使没有其他进程争用CPU时间。



更新:我需要能够限制所有正在运行的进程以及无源代码访问权限的进程。

解决方案

非常简化,它可以像这样工作:


  1. 使用合理的时间创建一个周期性的等待计时器等待时间短(也许100ms)。通过一次调用 GetProcessTimes 获得每个相关进程的最后值。

  2. 永远循环,阻塞计时器。

  3. 每次唤醒:

    • 如果 GetProcessAffinityMask 返回0,则调用 SetProcessAffinityMask(old_value)。这意味着我们已在上一次迭代中暂停了该过程,现在让它有机会再次运行。

    • 其他调用 GetProcessTimes 来获取当前值

    • call GetSystemTimeAsFileTime

    • 通过从当前值中减去最后一个来计算增量

    • cpu_usage =(deltaKernelTime + deltaUserTime)/(deltaTime)

    • 如果这超出了您的期望,请致电 old_value = GetProcessAffinityMask 后跟 SetProcessAffinityMask(0),它将使该过程脱机。


这基本上是调度程序的一个非常原始的版本,它运行在内核中,并在userland中实现。如果它使用的CPU时间超过您认为正确的时间,它将使进程休眠一小段时间。更复杂的测量可能需要一秒钟或5秒钟(也许是理想的)。但是,重要的是摆弄优先级,使用 SuspendThread 非常重要,除非您确切地知道程序是什么这样做会很容易导致死锁和其他令人讨厌的副作用。例如,考虑在另一个线程仍在运行时挂起一个持有关键部分的线程,并尝试获取同一对象。或想象一下,您的进程在暂停十二个线程的过程中被交换掉了,其中一半处于运行状态,另一半则处于死状态。



在另一方面只是意味着从现在开始,该进程中的任何线程都不会在任何处理器上获得更多的时间片。重置亲和力可以同时从原子上使所有线程再次运行。



不幸的是, SetProcessAffinityMask 不会像 SetThreadAffinityMask 那样返回旧掩码。因此,必须额外调用 Get ...


There is programs that is able to limit the CPU usage of processes in Windows. For example BES and ThreadMaster. I need to write my own program that does the same thing as these programs but with different configuration capabilities. Does anybody know how the CPU throttling of a process is done (code)? I'm not talking about setting the priority of a process, but rather how to limit it's CPU usage to for example 15% even if there is no other processes competing for CPU time.

Update: I need to be able to throttle any processes that is already running and that I have no source code access to.

解决方案

Very simplified, it could work somehow like this:

  1. Create a periodic waitable timer with some reasonable small wait time (maybe 100ms). Get a "last" value for each relevant process by calling GetProcessTimes once.
  2. Loop forever, blocking on the timer.
  3. Each time you wake up:
    • if GetProcessAffinityMask returns 0, call SetProcessAffinityMask(old_value). This means we've suspended that process in our last iteration, we're now giving it a chance to run again.
    • else call GetProcessTimes to get the "current" value
    • call GetSystemTimeAsFileTime
    • calculate delta by subtracting last from current
    • cpu_usage = (deltaKernelTime + deltaUserTime) / (deltaTime)
    • if that's more than you want call old_value = GetProcessAffinityMask followed by SetProcessAffinityMask(0) which will take the process offline.

This is basically a very primitive version of the scheduler that runs in the kernel, implemented in userland. It puts a process "to sleep" for a small amount of time if it has used more CPU time than what you deem right. A more sophisticated measurement maybe going over a second or 5 seconds would be possible (and probably desirable).

You might be tempted to suspend all threads in the process instead. However, it is important not to fiddle with priorities and not to use SuspendThread unless you know exactly what a program is doing, as this can easily lead to deadlocks and other nasty side effects. Think for example of suspending a thread holding a critical section while another thread is still running and trying to acquire the same object. Or imagine your process gets swapped out in the middle of suspending a dozen threads, leaving half of them running and the other half dead.

Setting the affinity mask to zero on the other hand simply means that from now on no single thread in the process gets any more time slices on any processor. Resetting the affinity gives -- atomically, at the same time -- all threads the possibility to run again.

Unluckily, SetProcessAffinityMask does not return the old mask as SetThreadAffinityMask does, at least according to the documentation. Therefore an extra Get... call is necessary.

这篇关于如何限制Windows上进程的CPU使用率? (需要代码,而不是应用程序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆