59

Of late, I'm becoming more health oriented when constructing my program, I have observed that most of programs take 2 or 3 minutes to execute and when I check on the task scheduler, I see that they consume 100% of CPU usage, can I limit this usage programatically in code? This will certainly enable me to run multiple programs at a given time.

Thanks, Nidhi

Shog9
  • 156,901
  • 35
  • 231
  • 235
Nidhi
  • 667
  • 3
  • 8
  • 12

13 Answers13

131

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));
    }
}
Ryan
  • 3,852
  • 4
  • 18
  • 18
  • 35
    +1 I hate when all people can say is "Don't do that". There may be reasons beyond what people understand of a problem, and yet they treat the asker as if he's just new to this stuff and doesn't know anything. By the way Your code in C# is what I've been looking for and yes, I am developing a background service - according to other answers I should kill the users' CPUs with it. – Przemysław Wrzesiński Jul 14 '15 at 07:56
  • 3
    @PrzemysławWrzesiński you are right 100%. I have come across a network appliance situation where it logs streams AT SCALE and a periodic process for extracting portions is not allowed to take more than 10% of the CPU, ever, because the primary function is to capture the massive streams and the CPU is being taxed and hardware engineering can't do anymore than they are doing. So this is a very valid question. – Snowy Jul 24 '15 at 23:29
  • 6
    " it still annoys me that the accepted answer criticizes the question rather than answering it" --- I think likewise. People should answer rather than asking why the hell someone asked it. By the way I have a very similar app that makes cpu shoot 95% and i want it to run longer but must not spike CPU to 95% every time. – Simple Fellow Oct 25 '15 at 10:56
  • 1
    It seems that this approach is problematic. It seems that a Stopwatch object measures the elapsed time, not only the time that is consumed by the current thread. – zhoudu Mar 12 '17 at 10:56
  • Would that result in 100% usage and then 0% usage and then 100% usage and so on? Is there any way to just keep it at a stable 30%? – Byte11 May 04 '18 at 17:03
  • Maybe someday OS task schedulers will have an energy-performance tradeoff preference for each process, as well as / connected with a scheduling priority. (On Skylake where the OS can hand over full control of P-states to the HW, Intel literally does have an `energy_performance_preference` setting, at least with that name in the Linux driver. `/sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference` can be set to balance_power, balance_performance, or pure perf or power.) With OS-managed CPU powersave, a task below a certain priority could just not count as load...) – Peter Cordes May 08 '18 at 07:25
  • Anyway, until we have better ways to signal preferences to CPU frequency governors, frequent artificial sleeps are probably a good idea. This also works on Linux to keep the frequency low: [Why does this delay-loop start to run faster after several iterations with no sleep?](https://stackoverflow.com/q/38299023) – Peter Cordes May 08 '18 at 07:26
  • @PrzemysławWrzesiński Any luck with final solution? How did you approached to the solution? – Mayur Aug 02 '21 at 16:54
  • Wish I could help, but I'm afraid it was a few years ago and I don't even remember which project I needed this for – Przemysław Wrzesiński Aug 02 '21 at 19:14
26

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.

Marc
  • 12,706
  • 7
  • 61
  • 97
  • Awesome, this is the kind of low level answer I was hoping for when I first found this question. If I understand correctly, this can work to throttle external third party processes on the system which could be very useful in some situations. – Ryan Oct 26 '15 at 17:21
  • 1
    Hi @Ryan, yes, it does. In my scenario I basically spawn a process with `Process.Start` and then throttle it down. You might need UAC (admin rights) to throttle a process you haven't spawned yourself. I haven't tried that yet. I'm glad you like it and hope you can still use it.... – Marc Oct 26 '15 at 17:42
25

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’

Community
  • 1
  • 1
Shog9
  • 156,901
  • 35
  • 231
  • 235
  • 19
    And it would be wasteful to NOT use 100% if it's available and can be utilized. Of course, this may reflect poor design in the program, so make sure you don't have any Schlemiel algorithms. See http://en.wikipedia.org/wiki/Schlemiel_the_painter%27s_Algorithm – Instance Hunter Jun 12 '09 at 22:15
  • 4
    What about something like a game, where you might want the game loop to become idle when the game is paused or minimized? Certainly reducing utilization would be appropriate there. – Matthew Olenik Jun 12 '09 at 22:52
  • 2
    @Matt: well, yeah, if you don't have anything to do, then by all means do nothing! But still, you're better off letting the OS handle this (via a blocking system call of some sort) - you just can't assume that your program ever has enough information about the system as a whole to throttle itself effectively, and may well end up being counter-productive (imagine a game that forced its loop down to 1% CPU while minimized... sounds great, right? But that's still enough to burn through your laptop battery... – Shog9 Jun 12 '09 at 23:04
  • 2
    +1. Your system should be using all as much of it's CPU and memory as possible, otherwise it's wasted. The OS should decide how to allocate those resources, not any single program. In fact, Windows does that with memory, I believe. If you don't use it, it starts using it itself for disk buffers and such. – paxdiablo Jun 13 '09 at 02:35
  • 3
    There are cases when you explicitly do not want to use all the available CPU. One such case (my case :) ) is a program that does work on the background of a Desktop wich is dedicated to a user and you do not want to block the users work alltogether but you want 10-20% of its CPU which will not bring his machine to a halt. That is perfect when you have 100+ desktops in the office with monstrous characteristics (for machine engineers) and you have parallel tasks - put your app in a windows service on them through Domain Controller but limit your app so you do not halt the engineers PC! :) – Ognyan Dimitrov Apr 28 '15 at 06:46
  • Is there a way of doing this at a more granular level? – ryanwebjackson Nov 16 '18 at 17:52
  • One of many examples of why this is a bad answer: https://superuser.com/questions/214566/ It's not necessarily "the job of the OS". We live in the real world and it can be really for cpu-intensive to provide a way to limit themselves. I just spent 3 hours searching for the beast 'workaround' to do that b/c the BOINC project doesn't offer that option, only a 'thread number'. Which doesn't do much for temps (my issue) when your cpu can turbo boost 4+Ghz in that single thread configured there. – Vinícius M Jul 04 '20 at 23:31
  • I would have to disagree there, @ViníciusM - preventing overheating is definitely more in the OS's realm, if not the firmware. While I'm sympathetic to the asker there, they're trying to hack around a situation that should never happen to begin with and *definitely* isn't better solved by relying on each individual app to cap its own cpu usage! – Shog9 Jul 06 '20 at 02:35
  • 1
    @ViníciusM If you want to see an example of the OS taking the thermal limits into account, see Linux Thermal Pressure https://www.phoronix.com/scan.php?page=news_item&px=Linux-5.7-Thermal-Pressure – Braiam Jul 12 '20 at 20:53
  • Hey @Braiam! Thanks for the input. See, I don't have a problem with thermal limits. I have a problem with *sound* (which raises with high temperates b/c high-cpu usage). I think Shog9 raises a fair point, but I STILL maintain that sometimes it is desirable, for e.g. exactly in the aforementioned BOINC or F@H projects. I'm volunteering CPU time after all. I don't want to "use all available processing power." It's not wasteful. ;) Besides the energy bill, what I don't want is a computer making a lot of noise. My cooling is fine -> which is the problem: cooling noise hehe. That's just 1 example. – Vinícius M Jul 14 '20 at 11:23
  • @ViníciusM Linus made a system that tries to achieve that, based on Treadripper. You could instead limit the fans so that the cpu throttles itself when temperatures rises. – Braiam Jul 14 '20 at 15:18
16

You could write a Governor class that throttles the CPU usage. This class would contain a utility method that should be called on a regular basis (e.g. calling this utility function within a while loop of your function) by your CPU bound function. The governor would check if the amount of time elapsed exceeded a particular threshold, and then sleep for a period of time so as to not consume all the CPU.

Here's a simple Java implementation off the top of my head (just so you get the idea) that will throttle the CPU usage to 50% if you have a single threaded CPU bound function.

public class Governor
{
  long start_time;

  public Governor()
  {
    this.start_time = System.currentTimeMillis();
  }

  public void throttle()
  {
    long time_elapsed = System.currentTimeMillis() - this.start_time;

    if (time_elapsed > 100) //throttle whenever at least a 100 millis of work has been done
    {
      try { Thread.sleep(time_elapsed); } catch (InterruptedExceptione ie) {} //sleep the same amount of time

      this.start_time = System.currentTimeMillis(); //reset after sleeping.
    }
  }
}

Your CPU bound function would instantiate a Governor, and then just call throttle on a regular basis within the function.

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
mal
  • 171
  • 1
  • 3
  • 5
    -1. This is a terrible idea. Your application should use as many system resources as it can (within reason, using all the handles in windows would be silly). Leave the OS to manage the allocation of such. – Gregory Dec 10 '09 at 05:07
  • 20
    Not necessarily - you can't rely on other external things managing how your application runs for you. I've seen this used many places before - even some versions of SQL Server have a resource governor. As an example, if your application is providing a service, but includes background tasks that maintain the application that could be CPU bound, the background tasks should not take up all the CPU, while denying service to users. You cannot leave such an implementation to the O.S. to manage. This is just one reason. There are many others. – mal Dec 10 '09 at 15:31
5

Thank all of you for answering. I've been working on this and the exe it runs for a few hours and want to share to help others. I wrote a class I'm going to set and forget in a WPF app that'll encrypt and push data to the cloud, but I couldn't ever have it ever interfere with the timing of the WPF app and what the WPF app needs in the way of resources, which I am also going to add a flag to disable when the WPF app is in it's highest resource consumption state. I've already highly threaded this WPF with the TPL. This solution has both the priority set of the process

myProcess.PriorityClass = ProcessPriorityClass.Idle;

and the CPU percentage limited.

then in my mainDisplay.xaml.cs I'll use

ProcessManagement.StartProcess(5);

in MainWindow()

And there is no window popping up when that exe is run

RedirectStandardOutput = true,  
UseShellExecute = false,
CreateNoWindow = true

in the object initalizer

internal class ProcessManagement
{
    private static int CpuPercentageLimit { get; set; }

    public static void StartProcess(int cpuPercent)
    {
        CpuPercentageLimit = cpuPercent;
        var stopwatch = new Stopwatch();
        while (true)
        {
            stopwatch.Reset();
            stopwatch.Start();
            var actionStart = stopwatch.ElapsedTicks;
            try
            {
                var myProcess = new Process
                {
                    StartInfo =
                    {
                        FileName = @"D:\\Source\\ExeProgram\\ExeProgram\\bin\\Debug\\ExeProgram.exe",
                        RedirectStandardOutput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true
                    }
                };
                myProcess.Start();
                myProcess.PriorityClass = ProcessPriorityClass.Idle;
                myProcess.Refresh();
                myProcess.WaitForExit();
                var actionEnd = stopwatch.ElapsedTicks;
                var actionDuration = actionEnd - actionStart;
                long relativeWaitTime = (int)((1 / (double)CpuPercentageLimit) * actionDuration);
                var sleepTime = (int)((relativeWaitTime / (double)Stopwatch.Frequency) * 1000);
                Thread.Sleep(sleepTime);
                myProcess.Close();
            }
            catch (Exception e)
            {
                // ignored
            }
        }
    }
}

In my application, there is ample time, like 24/7/365, to upload lots of data, including thousands of images, but the UI also needs to stay active when used and when the system runs, nothing else can be running.

Stephen Himes
  • 655
  • 9
  • 13
4

If you have a multi core processor, you can set the Affinity on each process to only use which cores you want it to use. This is the closest method I know of. But it will only allow you to assign percentages that are a factor of 50% on a dual core, and 25% on a quad core.

Scott Hunt
  • 41
  • 1
  • 1
    This only has any effect for a multi-threaded process, unless you set the affinity of multiple processes to one core and leave the other core idle. Having a thread using 100% of one core on a quad-core CPU is not different from having it use 100% of one core on a single-core CPU, if nothing else is running. The only thing that changes is Windows Task Manager dividing the load average by the number of available cores. – Peter Cordes May 08 '18 at 07:16
3

According to MSDN, you can only set a thread priority, i.e.

var t1 = new Thread(() => doSomething());
t1.Priority = ThreadPriority.BelowNormal;
t1.Start();

where doSomething is the function you want to create a thead for. The priority can be one of the ThreadPriority enumeration members Lowest, BelowNormal, Normal, AboveNormal, Highest - for a description see the MSDN link above. Priority Normal is the default.

Note that CPU usage also depends on how many cores and logical processors your physical CPU has *) - and how the threads and processes are assigned to those cores (the assignment to a dedicated processor is called "processor affinity" - if you want to know more about that, see this StackOverflow question).


*) To find that out, open the task manager (via Ctrl+Alt+Delete - select "task manager"), go to Performance and select CPU there: Below the utilization graph you can see "Cores" and "Logical processors".
A core is a physical unit built into the CPU, while a logical processor is just an abstraction, which means the more cores your CPU consists of, the faster it can process parallel tasks.

Matt
  • 25,467
  • 18
  • 120
  • 187
3

You can run your program in a thread with a lower threadpriority, the rest is up to your operating system. Having a process eat up 100% of your CPU is not bad. My SETI is usually taking up all my remaining CPU time without bothering my other programs. It only gets a problem when your thread gets priority over more important programs.

Carra
  • 17,808
  • 7
  • 62
  • 75
  • IIRC SETI only uses spare clock cycles so while the machine shows 100% cpu it is still responsive and as soon as something else requires processing power and starts to use the cpu the number of spare clock cycles is reduced so SETI gets limited not other processes. – OneSHOT Jun 26 '09 at 13:34
  • This is because SETI runs with the lowest allowed thread priority, and the OS handles the throttling. – Gregory Dec 10 '09 at 05:04
  • What is the definition of "spare"? SETI uses CPU cycles which are "spare" by setting it's priority very low (lower than the other programs which you want to remain responsive). If there are higher priority processes running then SETI won't be given any cycles. – David Dec 10 '09 at 05:10
1

If you code is running at all, it is at 100%

I suppose slipping in some sleeps might have an effect.

I have to wonder about that 2-3 minute figure. I've seen it too, and I suppose it's loading and initializing lots of stuff I probably don't really need.

Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
0

This is something I have come across a lot of times with complex integrations (for example a daily update of products, stock and pricing on an ecomm system).

Writing the integrations as efficiently as possible is always good, using DB server power where you can instead for iterating objects in the code but at the end of the day these things WILL take up processor time and you may want to run them on a server that is doing other things too.

Sharing is caring ;-)

A good approach to avoid coding a Governor or Throttling mechanism is to use the power of a web server. Expose the integration as a "local API call" and run it in IIS (for instance). There you have multiple throttling options and affinity masks you can apply to the application pool. This can then be easily adjusted "on the fly" to give a good balance and monitor closely.

Cueball 6118
  • 517
  • 4
  • 16
0

I honestly think rather than worry about trying to limit CPU utilization by your app, you should focus more of your energies on profiling the application to uncover and correct bottlenecks and inefficiencies that may exist.

itsmatt
  • 31,265
  • 10
  • 100
  • 164
-2

If there is no other task running, is it wrong for your app to use all the cpu capacity that is available? It is available, as in it's there and it is free to use. So use it!

If you somehow limit the cpu usage of your task, it will take longer to complete. But it will still take the same number of cpu cycles, so you gain nothing. You just slow down your application.

Don't do it. Don't even try it. There's no reason why you should.

Treb
  • 19,903
  • 7
  • 54
  • 87
  • 9
    Yeah, why should "System Idle Task" have all the fun? – paxdiablo Jun 13 '09 at 02:36
  • 2
    @paxdiablo because battery life. – Ryan Nov 06 '15 at 08:53
  • Lets assume that you reduce the cpu usage to 50%, which in turn reduces the power consumption by 50%. Lets further assume that the computation with 50% less cpu usage will take twice as long as with 100% usage. In this (admittedly rather simple) scenario, your overall power consumption *does not change at all*. Therefore I don't think that this is worth spending time thinking about. – Treb Sep 27 '17 at 09:42
  • 1
    So many assumptions, but in reality the power consumption decreases faster with lower CPU speed. – Ladislav Zima Aug 06 '19 at 13:37
  • 1
    I'm sorry but EVERY thing in this answer is not strictly true. "There's no reason why you should" Just because we may lack the imagination at the time, doesn't mean there couldn't be a reason. One such is: https://superuser.com/questions/214566/ But there are many more. – Vinícius M Jul 04 '20 at 23:36
  • To provide some context for my answer, have a look at the year I posted it. Back in 2009, most of us were still using desktop computers, not laptops. Battery life was not a big concern for us :-) It also was still quite common to have only one CPU with one core. Most dev computers today have at least 4 cores, so the spike OP saw in his task manager would be at 25% now, not 100%. And, most important from my current POV, I was quite a bit younger. Today my answer wouldn't be as brash and absolute as it was 13 years ago. However, for the case in the question I'd still say "don't worry about it". – Treb Feb 08 '22 at 10:49
-3

I think what you need to do is to understand the performance problem in your application instead of trying to put a cap on the CPU usage. You Can use Visual Studio Profiler to see why you application is taking 100% CPU for 2-3 minutes in the first place. This should reveal the hot spot in your app, and then you can be able to address this issue.

If you are asking in general regarding how to do resource throttling in windows, then you can look at the "Task" objects, Job objects allows you to set limits such as Working set, process priority...etc.

You can check out the Job objects documentation here http://msdn.microsoft.com/en-ca/library/ms684161(VS.85).aspx Hope this helps. Thanks

mfawzymkh
  • 4,030
  • 1
  • 16
  • 12