CPUSetter Help
Process Limiting
There are four subsystems used by CPUSetter that are involved in
limiting the cpu usage of a process.
- 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).
- 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.
- 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.
- 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)