### CPUSetter Help

## Process Limiting

There are four subsystems used by CPUSetter that are involved in limiting the cpu usage of a process.

1. The user interface. Select which processes are to be limited and by how much each is limited. Also display the effect of the limiting. The user interface updates at a user selected interval (default 5s).
2. Process Monitor. This subsytem runs every second and keeps track of all the processes in the system, calculating the percentage of the available cpu resource used by each process over the interval.
3. Process Limiter. This subsystem runs every 30ms by default. The interval can be adjusted by the user in the CPUSetter Preferences window.

- When a process is first limited it is added to a queue of limited processes and the total cpu time that the process has used is saved in the queue entry. When a limited process terminates or limiting is removed by the user, the process is removed from the queue. When CPUSetter itself terminates, all limited processes are sent the SIGSTRT signal so they will resume unlimited operation.
- Each time it runs (every 30 ms), the limiter credits cpu time to each limited process, the size of the credit being determined by the percentage limiting of the process. e.g. If a process is limited to 10% then it will be allocated 3000µsec at each interval.
- The limiter then asks macOS for the total cpu time used by the process. The cpu time that has been used by the process during the interval is the difference between this current value and the time used stored in the queue entry.
- The queue entry is updated with the current value for total cpu time.
- The cpu time credit is reduced by the amount of cpu time that has been used during the interval and stored into the queue entry.
- If the credit is less than or equal 0, i.e. the process has used more than its allocated share of cpu time, then the process is stopped by sending it a SIGSTOP signal. It is no longer running and no longer using the cpu.
- If however the credit is greater than 0, the process is allowed to run again. If it is in a stopped state (i.e. had previously used all its credit) then it is sent a SIGSTRT signal, and its cpu usage will resume.

4. Limit Adjuster. The limiting algorithm described above takes no account of inaccuracy of the interval timer (it may be off by several ms), latency in delivering signals to processes or retrieving process attributes from the macOS kernel. If nothing is done to compensate for these delays and inaccuracies, the limiter tends to be too agressive and the limited process will only ever achieve about 80% of it’s allowed cpu usage. Rather than compensating for individual sources of latency and errors, CPUSetter uses negative feedback principles to bring things back into line by using an adjuster that runs every 500ms.

- If a limited process has not been stopped in the last second, then no adjustment is required as the process is not making demands for cpu that exceed its limit.
- The average utilisation of the process during the previous second is calculated. i.e. the difference between the total cpu used at the start of the interval and the current value of the total cpu. Dividing the usage by the time since the adjuster last ran (nominally 1 second but it my be off by a few ms) gives the average usage over the interval. The difference between this actual usage and the limit set by the user represents the inaccuracies in the limiter subsytem. The credit granted to the process by the limiter at each limiter cycle is ajusted by this difference. e.g. Using the 30 ms interval, 10% limit example from above, each cycle credits the process with 3000µsec of allowed cpu time. If the actual usage is 10% lower than the nominal usage, the credit adjustment is increased to 3300µsec. Conversely, If the actual usage is 10% higher than the nominal usage the credit adjustment is reduced to 2700µsec.
- Successive applications of this adjustment lead to convergence very close to the nominal cpu usage set by the user.
- A further refinement to the Limit Adjuster algorithm, is to treat the adjuster as a PID controller. As described above, the limiter is in fact a P controller where the proportional coefficent has a value of 1.0. The Limit Adjuster also calculates the integral of the usage offset and the derivative of this offset. Using coefficients from CPUSetter Preferences the user can also fine tune the algorithm to give very close and responsive tracking of the nominal value of cpu usage by the process. The default coefficients defined in CPUSetter Preferences have been determined experimentally. Trial and error may lead to better estimates of these coefficients.

Copyright © 2018-2022 B.R. Christianson (bryan@whatroute.net)