How can I programmatically limit my program's CPU usage to below 70%?
This thread is over four years old, and it still annoys me that the accepted answer criticizes the question rather than answering it. There are many valid reasons you would want to limit the CPU time taken by your program, I can list a few off the top of my head.
It might seem like a waste not to use all free CPU cycles available, but this mentality is flawed. Unlike older CPUs, most modern CPUs do not run at a fixed clock speed - many have power saving modes where they drop the clock speed and cpu voltage when load is low. CPUs also consume more power when performing calculations than they do running NOOPs. This is especially relevant to laptops that require fans to cool the CPU when it is under high load. Running a task at 100% for a short time can use far more energy than running a task at 25% for four times as long.
Imagine you are writing a background task that is designed to index files periodically in the background. Should the indexing task use as much of the CPU as it can at a lower priority, or throttle itself to 25% and take as long as it needs? Well, if it were to consume 100% of the CPU on a laptop, the CPU would heat up, the fans would kick in, and the battery would drain fairly quickly, and the user would get annoyed. If the indexing service throttled itself, the laptop may be able to run with completely passive cooling at a very low cpu clock speed and voltage.
Incidentally, the Windows Indexing Service now throttles itself in newer versions of Windows, which it never did in older versions. For an example of a service that still doesn't throttle itself and frequently annoys people, see Windows Installer Module.
An example of how to throttle part of your application internally in C#:
public void ThrottledLoop(Action action, int cpuPercentageLimit) {
Stopwatch stopwatch = new Stopwatch();
while(true) {
stopwatch.Reset();
stopwatch.Start();
long actionStart = stopwatch.ElapsedTicks;
action.Invoke();
long actionEnd = stopwatch.ElapsedTicks;
long actionDuration = actionEnd - actionStart;
long relativeWaitTime = (int)(
(1/(double)cpuPercentageLimit) * actionDuration);
Thread.Sleep((int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000));
}
}
That's not your concern... It's the job of the operating system to distribute processor time between running processes. If you'd like to give other processes first crack at getting their stuff done, then simply reduce the priority of your own process by modifying the Process.PriorityClass
value for it.
See also: Windows Equivalent of ‘nice’
First of all, I agree with Ryan that the question is perfectly valid and there are cases where thread priorities are not at all sufficient. The other answers appear highly theoretical and of no practical use in situations where the application is properly designed but still needs to be throttled. Ryan offers a simple solution for cases in which a relatively short task is performed in high frequency. There are cases, however, when the task takes a very long time (say a minute or so) and you cannot or don't want to break it into smaller chunks between which you can do the throttling. For these cases the following solution might be helpful:
Rather that implementing throttling into the business code, you can design the algorithm itself to work at full steam and simply throttle the thread which runs the operation "from the outside". The general approach is the same as in Ryan's answer: Calculate a suspension time based on the current usage and suspend the thread for this timespan before resuming it again. Given a process which you want to throttle, this is the logic:
public static class ProcessManager
{
[Flags]
public enum ThreadAccess : int
{
TERMINATE = (0x0001),
SUSPEND_RESUME = (0x0002),
GET_CONTEXT = (0x0008),
SET_CONTEXT = (0x0010),
SET_INFORMATION = (0x0020),
QUERY_INFORMATION = (0x0040),
SET_THREAD_TOKEN = (0x0080),
IMPERSONATE = (0x0100),
DIRECT_IMPERSONATION = (0x0200)
}
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern uint SuspendThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int ResumeThread(IntPtr hThread);
[DllImport("kernel32.dll")]
static extern int CloseHandle(IntPtr hThread);
public static void ThrottleProcess(int processId, double limit)
{
var process = Process.GetProcessById(processId);
var processName = process.ProcessName;
var p = new PerformanceCounter("Process", "% Processor Time", processName);
while (true)
{
var interval = 100;
Thread.Sleep(interval);
var currentUsage = p.NextValue() / Environment.ProcessorCount;
if (currentUsage < limit) continue;
var suspensionTime = (currentUsage-limit) / currentUsage * interval;
SuspendProcess(processId);
Thread.Sleep((int)suspensionTime);
ResumeProcess(processId);
}
}
private static void SuspendProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
SuspendThread(pOpenThread);
CloseHandle(pOpenThread);
}
}
private static void ResumeProcess(int pid)
{
var process = Process.GetProcessById(pid);
if (process.ProcessName == string.Empty)
return;
foreach (ProcessThread pT in process.Threads)
{
IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id);
if (pOpenThread == IntPtr.Zero)
{
continue;
}
var suspendCount = 0;
do
{
suspendCount = ResumeThread(pOpenThread);
} while (suspendCount > 0);
CloseHandle(pOpenThread);
}
}
}
The benefit of this solution is that the checking interval becomes independent of the duration of your "long running task". Furthermore, business logic and throttling logic are separated. The suspense/resume code is inspired by this thread. Please note that disposal and ending the throttling needs to be implemented in the solution above, it is not production code.