|  | ========================================== | 
|  | Reducing OS jitter due to per-cpu kthreads | 
|  | ========================================== | 
|  |  | 
|  | This document lists per-CPU kthreads in the Linux kernel and presents | 
|  | options to control their OS jitter.  Note that non-per-CPU kthreads are | 
|  | not listed here.  To reduce OS jitter from non-per-CPU kthreads, bind | 
|  | them to a "housekeeping" CPU dedicated to such work. | 
|  |  | 
|  | References | 
|  | ========== | 
|  |  | 
|  | -	Documentation/core-api/irq/irq-affinity.rst:  Binding interrupts to sets of CPUs. | 
|  |  | 
|  | -	Documentation/admin-guide/cgroup-v1:  Using cgroups to bind tasks to sets of CPUs. | 
|  |  | 
|  | -	man taskset:  Using the taskset command to bind tasks to sets | 
|  | of CPUs. | 
|  |  | 
|  | -	man sched_setaffinity:  Using the sched_setaffinity() system | 
|  | call to bind tasks to sets of CPUs. | 
|  |  | 
|  | -	/sys/devices/system/cpu/cpuN/online:  Control CPU N's hotplug state, | 
|  | writing "0" to offline and "1" to online. | 
|  |  | 
|  | -	In order to locate kernel-generated OS jitter on CPU N: | 
|  |  | 
|  | cd /sys/kernel/debug/tracing | 
|  | echo 1 > max_graph_depth # Increase the "1" for more detail | 
|  | echo function_graph > current_tracer | 
|  | # run workload | 
|  | cat per_cpu/cpuN/trace | 
|  |  | 
|  | kthreads | 
|  | ======== | 
|  |  | 
|  | Name: | 
|  | ehca_comp/%u | 
|  |  | 
|  | Purpose: | 
|  | Periodically process Infiniband-related work. | 
|  |  | 
|  | To reduce its OS jitter, do any of the following: | 
|  |  | 
|  | 1.	Don't use eHCA Infiniband hardware, instead choosing hardware | 
|  | that does not require per-CPU kthreads.  This will prevent these | 
|  | kthreads from being created in the first place.  (This will | 
|  | work for most people, as this hardware, though important, is | 
|  | relatively old and is produced in relatively low unit volumes.) | 
|  | 2.	Do all eHCA-Infiniband-related work on other CPUs, including | 
|  | interrupts. | 
|  | 3.	Rework the eHCA driver so that its per-CPU kthreads are | 
|  | provisioned only on selected CPUs. | 
|  |  | 
|  |  | 
|  | Name: | 
|  | irq/%d-%s | 
|  |  | 
|  | Purpose: | 
|  | Handle threaded interrupts. | 
|  |  | 
|  | To reduce its OS jitter, do the following: | 
|  |  | 
|  | 1.	Use irq affinity to force the irq threads to execute on | 
|  | some other CPU. | 
|  |  | 
|  | Name: | 
|  | kcmtpd_ctr_%d | 
|  |  | 
|  | Purpose: | 
|  | Handle Bluetooth work. | 
|  |  | 
|  | To reduce its OS jitter, do one of the following: | 
|  |  | 
|  | 1.	Don't use Bluetooth, in which case these kthreads won't be | 
|  | created in the first place. | 
|  | 2.	Use irq affinity to force Bluetooth-related interrupts to | 
|  | occur on some other CPU and furthermore initiate all | 
|  | Bluetooth activity on some other CPU. | 
|  |  | 
|  | Name: | 
|  | ksoftirqd/%u | 
|  |  | 
|  | Purpose: | 
|  | Execute softirq handlers when threaded or when under heavy load. | 
|  |  | 
|  | To reduce its OS jitter, each softirq vector must be handled | 
|  | separately as follows: | 
|  |  | 
|  | TIMER_SOFTIRQ | 
|  | ------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	To the extent possible, keep the CPU out of the kernel when it | 
|  | is non-idle, for example, by avoiding system calls and by forcing | 
|  | both kernel threads and interrupts to execute elsewhere. | 
|  | 2.	Build with CONFIG_HOTPLUG_CPU=y.  After boot completes, force | 
|  | the CPU offline, then bring it back online.  This forces | 
|  | recurring timers to migrate elsewhere.	If you are concerned | 
|  | with multiple CPUs, force them all offline before bringing the | 
|  | first one back online.  Once you have onlined the CPUs in question, | 
|  | do not offline any other CPUs, because doing so could force the | 
|  | timer back onto one of the CPUs in question. | 
|  |  | 
|  | NET_TX_SOFTIRQ and NET_RX_SOFTIRQ | 
|  | --------------------------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	Force networking interrupts onto other CPUs. | 
|  | 2.	Initiate any network I/O on other CPUs. | 
|  | 3.	Once your application has started, prevent CPU-hotplug operations | 
|  | from being initiated from tasks that might run on the CPU to | 
|  | be de-jittered.  (It is OK to force this CPU offline and then | 
|  | bring it back online before you start your application.) | 
|  |  | 
|  | BLOCK_SOFTIRQ | 
|  | ------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	Force block-device interrupts onto some other CPU. | 
|  | 2.	Initiate any block I/O on other CPUs. | 
|  | 3.	Once your application has started, prevent CPU-hotplug operations | 
|  | from being initiated from tasks that might run on the CPU to | 
|  | be de-jittered.  (It is OK to force this CPU offline and then | 
|  | bring it back online before you start your application.) | 
|  |  | 
|  | IRQ_POLL_SOFTIRQ | 
|  | ---------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	Force block-device interrupts onto some other CPU. | 
|  | 2.	Initiate any block I/O and block-I/O polling on other CPUs. | 
|  | 3.	Once your application has started, prevent CPU-hotplug operations | 
|  | from being initiated from tasks that might run on the CPU to | 
|  | be de-jittered.  (It is OK to force this CPU offline and then | 
|  | bring it back online before you start your application.) | 
|  |  | 
|  | TASKLET_SOFTIRQ | 
|  | --------------- | 
|  |  | 
|  | Do one or more of the following: | 
|  |  | 
|  | 1.	Avoid use of drivers that use tasklets.  (Such drivers will contain | 
|  | calls to things like tasklet_schedule().) | 
|  | 2.	Convert all drivers that you must use from tasklets to workqueues. | 
|  | 3.	Force interrupts for drivers using tasklets onto other CPUs, | 
|  | and also do I/O involving these drivers on other CPUs. | 
|  |  | 
|  | SCHED_SOFTIRQ | 
|  | ------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	Avoid sending scheduler IPIs to the CPU to be de-jittered, | 
|  | for example, ensure that at most one runnable kthread is present | 
|  | on that CPU.  If a thread that expects to run on the de-jittered | 
|  | CPU awakens, the scheduler will send an IPI that can result in | 
|  | a subsequent SCHED_SOFTIRQ. | 
|  | 2.	CONFIG_NO_HZ_FULL=y and ensure that the CPU to be de-jittered | 
|  | is marked as an adaptive-ticks CPU using the "nohz_full=" | 
|  | boot parameter.  This reduces the number of scheduler-clock | 
|  | interrupts that the de-jittered CPU receives, minimizing its | 
|  | chances of being selected to do the load balancing work that | 
|  | runs in SCHED_SOFTIRQ context. | 
|  | 3.	To the extent possible, keep the CPU out of the kernel when it | 
|  | is non-idle, for example, by avoiding system calls and by | 
|  | forcing both kernel threads and interrupts to execute elsewhere. | 
|  | This further reduces the number of scheduler-clock interrupts | 
|  | received by the de-jittered CPU. | 
|  |  | 
|  | HRTIMER_SOFTIRQ | 
|  | --------------- | 
|  |  | 
|  | Do all of the following: | 
|  |  | 
|  | 1.	To the extent possible, keep the CPU out of the kernel when it | 
|  | is non-idle.  For example, avoid system calls and force both | 
|  | kernel threads and interrupts to execute elsewhere. | 
|  | 2.	Build with CONFIG_HOTPLUG_CPU=y.  Once boot completes, force the | 
|  | CPU offline, then bring it back online.  This forces recurring | 
|  | timers to migrate elsewhere.  If you are concerned with multiple | 
|  | CPUs, force them all offline before bringing the first one | 
|  | back online.  Once you have onlined the CPUs in question, do not | 
|  | offline any other CPUs, because doing so could force the timer | 
|  | back onto one of the CPUs in question. | 
|  |  | 
|  | RCU_SOFTIRQ | 
|  | ----------- | 
|  |  | 
|  | Do at least one of the following: | 
|  |  | 
|  | 1.	Offload callbacks and keep the CPU in either dyntick-idle or | 
|  | adaptive-ticks state by doing all of the following: | 
|  |  | 
|  | a.	CONFIG_NO_HZ_FULL=y and ensure that the CPU to be | 
|  | de-jittered is marked as an adaptive-ticks CPU using the | 
|  | "nohz_full=" boot parameter.  Bind the rcuo kthreads to | 
|  | housekeeping CPUs, which can tolerate OS jitter. | 
|  | b.	To the extent possible, keep the CPU out of the kernel | 
|  | when it is non-idle, for example, by avoiding system | 
|  | calls and by forcing both kernel threads and interrupts | 
|  | to execute elsewhere. | 
|  |  | 
|  | 2.	Enable RCU to do its processing remotely via dyntick-idle by | 
|  | doing all of the following: | 
|  |  | 
|  | a.	Build with CONFIG_NO_HZ=y and CONFIG_RCU_FAST_NO_HZ=y. | 
|  | b.	Ensure that the CPU goes idle frequently, allowing other | 
|  | CPUs to detect that it has passed through an RCU quiescent | 
|  | state.	If the kernel is built with CONFIG_NO_HZ_FULL=y, | 
|  | userspace execution also allows other CPUs to detect that | 
|  | the CPU in question has passed through a quiescent state. | 
|  | c.	To the extent possible, keep the CPU out of the kernel | 
|  | when it is non-idle, for example, by avoiding system | 
|  | calls and by forcing both kernel threads and interrupts | 
|  | to execute elsewhere. | 
|  |  | 
|  | Name: | 
|  | kworker/%u:%d%s (cpu, id, priority) | 
|  |  | 
|  | Purpose: | 
|  | Execute workqueue requests | 
|  |  | 
|  | To reduce its OS jitter, do any of the following: | 
|  |  | 
|  | 1.	Run your workload at a real-time priority, which will allow | 
|  | preempting the kworker daemons. | 
|  | 2.	A given workqueue can be made visible in the sysfs filesystem | 
|  | by passing the WQ_SYSFS to that workqueue's alloc_workqueue(). | 
|  | Such a workqueue can be confined to a given subset of the | 
|  | CPUs using the ``/sys/devices/virtual/workqueue/*/cpumask`` sysfs | 
|  | files.	The set of WQ_SYSFS workqueues can be displayed using | 
|  | "ls /sys/devices/virtual/workqueue".  That said, the workqueues | 
|  | maintainer would like to caution people against indiscriminately | 
|  | sprinkling WQ_SYSFS across all the workqueues.	The reason for | 
|  | caution is that it is easy to add WQ_SYSFS, but because sysfs is | 
|  | part of the formal user/kernel API, it can be nearly impossible | 
|  | to remove it, even if its addition was a mistake. | 
|  | 3.	Do any of the following needed to avoid jitter that your | 
|  | application cannot tolerate: | 
|  |  | 
|  | a.	Build your kernel with CONFIG_SLUB=y rather than | 
|  | CONFIG_SLAB=y, thus avoiding the slab allocator's periodic | 
|  | use of each CPU's workqueues to run its cache_reap() | 
|  | function. | 
|  | b.	Avoid using oprofile, thus avoiding OS jitter from | 
|  | wq_sync_buffer(). | 
|  | c.	Limit your CPU frequency so that a CPU-frequency | 
|  | governor is not required, possibly enlisting the aid of | 
|  | special heatsinks or other cooling technologies.  If done | 
|  | correctly, and if you CPU architecture permits, you should | 
|  | be able to build your kernel with CONFIG_CPU_FREQ=n to | 
|  | avoid the CPU-frequency governor periodically running | 
|  | on each CPU, including cs_dbs_timer() and od_dbs_timer(). | 
|  |  | 
|  | WARNING:  Please check your CPU specifications to | 
|  | make sure that this is safe on your particular system. | 
|  | d.	As of v3.18, Christoph Lameter's on-demand vmstat workers | 
|  | commit prevents OS jitter due to vmstat_update() on | 
|  | CONFIG_SMP=y systems.  Before v3.18, is not possible | 
|  | to entirely get rid of the OS jitter, but you can | 
|  | decrease its frequency by writing a large value to | 
|  | /proc/sys/vm/stat_interval.  The default value is HZ, | 
|  | for an interval of one second.	Of course, larger values | 
|  | will make your virtual-memory statistics update more | 
|  | slowly.  Of course, you can also run your workload at | 
|  | a real-time priority, thus preempting vmstat_update(), | 
|  | but if your workload is CPU-bound, this is a bad idea. | 
|  | However, there is an RFC patch from Christoph Lameter | 
|  | (based on an earlier one from Gilad Ben-Yossef) that | 
|  | reduces or even eliminates vmstat overhead for some | 
|  | workloads at https://lkml.org/lkml/2013/9/4/379. | 
|  | e.	If running on high-end powerpc servers, build with | 
|  | CONFIG_PPC_RTAS_DAEMON=n.  This prevents the RTAS | 
|  | daemon from running on each CPU every second or so. | 
|  | (This will require editing Kconfig files and will defeat | 
|  | this platform's RAS functionality.)  This avoids jitter | 
|  | due to the rtas_event_scan() function. | 
|  | WARNING:  Please check your CPU specifications to | 
|  | make sure that this is safe on your particular system. | 
|  | f.	If running on Cell Processor, build your kernel with | 
|  | CBE_CPUFREQ_SPU_GOVERNOR=n to avoid OS jitter from | 
|  | spu_gov_work(). | 
|  | WARNING:  Please check your CPU specifications to | 
|  | make sure that this is safe on your particular system. | 
|  | g.	If running on PowerMAC, build your kernel with | 
|  | CONFIG_PMAC_RACKMETER=n to disable the CPU-meter, | 
|  | avoiding OS jitter from rackmeter_do_timer(). | 
|  |  | 
|  | Name: | 
|  | rcuc/%u | 
|  |  | 
|  | Purpose: | 
|  | Execute RCU callbacks in CONFIG_RCU_BOOST=y kernels. | 
|  |  | 
|  | To reduce its OS jitter, do at least one of the following: | 
|  |  | 
|  | 1.	Build the kernel with CONFIG_PREEMPT=n.  This prevents these | 
|  | kthreads from being created in the first place, and also obviates | 
|  | the need for RCU priority boosting.  This approach is feasible | 
|  | for workloads that do not require high degrees of responsiveness. | 
|  | 2.	Build the kernel with CONFIG_RCU_BOOST=n.  This prevents these | 
|  | kthreads from being created in the first place.  This approach | 
|  | is feasible only if your workload never requires RCU priority | 
|  | boosting, for example, if you ensure frequent idle time on all | 
|  | CPUs that might execute within the kernel. | 
|  | 3.	Build with CONFIG_RCU_NOCB_CPU=y and boot with the rcu_nocbs= | 
|  | boot parameter offloading RCU callbacks from all CPUs susceptible | 
|  | to OS jitter.  This approach prevents the rcuc/%u kthreads from | 
|  | having any work to do, so that they are never awakened. | 
|  | 4.	Ensure that the CPU never enters the kernel, and, in particular, | 
|  | avoid initiating any CPU hotplug operations on this CPU.  This is | 
|  | another way of preventing any callbacks from being queued on the | 
|  | CPU, again preventing the rcuc/%u kthreads from having any work | 
|  | to do. | 
|  |  | 
|  | Name: | 
|  | rcuop/%d and rcuos/%d | 
|  |  | 
|  | Purpose: | 
|  | Offload RCU callbacks from the corresponding CPU. | 
|  |  | 
|  | To reduce its OS jitter, do at least one of the following: | 
|  |  | 
|  | 1.	Use affinity, cgroups, or other mechanism to force these kthreads | 
|  | to execute on some other CPU. | 
|  | 2.	Build with CONFIG_RCU_NOCB_CPU=n, which will prevent these | 
|  | kthreads from being created in the first place.  However, please | 
|  | note that this will not eliminate OS jitter, but will instead | 
|  | shift it to RCU_SOFTIRQ. | 
|  |  | 
|  | Name: | 
|  | watchdog/%u | 
|  |  | 
|  | Purpose: | 
|  | Detect software lockups on each CPU. | 
|  |  | 
|  | To reduce its OS jitter, do at least one of the following: | 
|  |  | 
|  | 1.	Build with CONFIG_LOCKUP_DETECTOR=n, which will prevent these | 
|  | kthreads from being created in the first place. | 
|  | 2.	Boot with "nosoftlockup=0", which will also prevent these kthreads | 
|  | from being created.  Other related watchdog and softlockup boot | 
|  | parameters may be found in Documentation/admin-guide/kernel-parameters.rst | 
|  | and Documentation/watchdog/watchdog-parameters.rst. | 
|  | 3.	Echo a zero to /proc/sys/kernel/watchdog to disable the | 
|  | watchdog timer. | 
|  | 4.	Echo a large number of /proc/sys/kernel/watchdog_thresh in | 
|  | order to reduce the frequency of OS jitter due to the watchdog | 
|  | timer down to a level that is acceptable for your workload. |