Programmatically limit CPU Usage of a Thread running inside a Service

11,671

Solution 1

You can reduce the priority of the thread, in .Net via Thread.Priority

Setting it to BelowNormal will mean that other threads will be scheduled in front of it.

This can lead to the thread being starved, but it sounds like this is an acceptable design decision for your needs.

Note that since you are performing considerable disk IO this actually will be the main impact of the back ground task, and you may find that reducing the priority is not sufficient (since the disk IO will continue in parts even while the thread is throttled.

A monitoring thread that checks the usage of the machine (optionally caring only when at least one interactive user is present) could pause the indexing (or throttle the IO considerably). This will be more important on modern machines where there are many available cores (and hyper threading virtual cores) which mean that despite the user actually doing a lot of work spare resources exist to execute your indexing thread but not really to execute the disk IO.

You may also want to consider whether you check the Power Scheme to determine if you should run at that time (since the battery drain from both heavy disk access is not inconsiderable)

If you wish to do even more to reduce the impact of this background IO bound task versions of windows from Vista onwards add two useful APIs:

Low Priority I/O

This allows your code to schedule I/O at a lower priority than other I/O.

Windows Task Scheduler

You can use this to schedule things to run at "system idle time". This when the system isn't busy, and the user is not present.

Solution 2

On XP, ShuggyCoUk is correct. The first thing to do is simply lower the thread priority to something below 8. This will mean that any other thread or process that is running with priority 8 or greater will always run instead of your thread. Note, I do not recommend simply setting your process priority to <8, just the thread (or threads) you want to run 'nicely'.

As Shuggy has pointed out, the issue isn't he CPU time - it is the I/O your service is generating. On XP, all I/O's are treated the same - so your I/O has the potential to interfere with other things.

Vista (and soon on Win7) has two things designed to do exactly what you want.

The first is the Windows Task Scheduler. You can use this to schedule things to run at "system idle time". This when the system isn't busy, and the user is not present.

The second is Low Priority I/O. This allows your code to schedule I/O at a lower priority than other I/O.

Both of these together can be used to develop code that is a good system citizen.

Note, you should also take mobile systems into account by scaling back or disabling your background item when the system is running on batteries. You can be simple about this - simple turning off on battery power; or sophisticated, taking the Power Scheme into account, and using that as hint from the user.

Since you are working on writing a service that is a good system citizen, you can do a few other things as well.

1) You could monitor the amount of work done over time and slow down or stop if enough progress has been made. 2) Do pay attention to your memory footprint - the smaller the better. This often goes without saying, but it is particular important for services as they run 24/7.

Solution 3

If you use the SetThreadPriority API, you can configure the thread to use a lower thread priority than normal. The thread will use all available CPU resources when the system is idle, but will relinquish CPU time to any threads that have a higher priority.

Solution 4

Much of the burden on your system coming from your indexing process is probably the disk I/O, so besides what ShuggyCoUk said, if your process works in Vista/Windows Server 2008, you can also change disk I/O priority to background. That's how most paging, defrag and other maintenance tasks work on those systems. If not, you can also monitor the disk i/o queue to see if there are pending operations coming from user interaction.

Share:
11,671
user57175
Author by

user57175

Updated on July 28, 2022

Comments

  • user57175
    user57175 almost 2 years

    I'm using VB9 (VS2008).

    I've created a Windows Service that indexes some folders regularly.

    Is there a way I can put an upper limit on the CPU usage depending upon the current system state, i.e., if the system is idle, the thread can use the CPU as much as it needs, but if there are other programs/processes running then it should use the CPU in way that does not make the system slow.

  • ShuggyCoUk
    ShuggyCoUk about 15 years
    Your input is good, since my answer is accepted I will integrate it into mine and add community wiki