From: Ciunas Bennett <ciunas@linux.ibm.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Douglas Freimuth <freimuth@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Ilya Leoshkevich <iii@linux.ibm.com>,
mingo@kernel.org, Thomas Gleixner <tglx@linutronix.de>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
juri.lelli@redhat.com, vincent.guittot@linaro.org,
dietmar.eggemann@arm.com, rostedt@goodmis.org,
bsegall@google.com, mgorman@suse.de, vschneid@redhat.com,
clrkwllms@kernel.org, linux-kernel@vger.kernel.org,
linux-rt-devel@lists.linux.dev,
Linus Torvalds <torvalds@linux-foundation.org>,
linux-s390@vger.kernel.org,
Matthew Rosato <mjrosato@linux.ibm.com>,
Hendrik Brueckner <brueckner@linux.ibm.com>
Subject: Re: [PATCH] sched: Further restrict the preemption modes
Date: Fri, 5 Jun 2026 11:43:24 +0100 [thread overview]
Message-ID: <6c3fbb6d-d4e1-4984-b584-c067be844098@linux.ibm.com> (raw)
In-Reply-To: <20260303115235.GQ1282955@noisy.programming.kicks-ass.net>
On 03/03/2026 11:52, Peter Zijlstra wrote:
> This has two ramifications:
>
> 1) some ping-pong workloads will turn into block+wakeup, adding
> overhead.
>
> FULL: running your task A, an interrupt would come in, wake task B and
> set Need Resched and the interrupt return path calls schedule() and
> you're task B. B does its thing, 'wakes' A and blocks.
>
> LAZY: running your task A, an interrupt would come in, wake task B (no
> NR set), you continue running A, A blocks for it needs something of B,
> now you schedule() [*] B runs, does its thing, does an actual wakeup of
> A and blocks.
>
> The distinct difference here is that LAZY does a block of A and
> consequently B has to do a full wakeup of A, whereas FULL doesn't do a
> block of A, and hence the wakeup of A is NOP as well.
>
>
> 2) Since the schedule() is delayed, it might happen that by the time it
> does get around to it, your task B is no longer the most eligible
> option.
>
> Same as above, except now, C is also woken, and the schedule marked with
> [*] picks C, this then results in a detour, delaying things further.
>
>
>
Hi Peter,
I wanted to share an update/findings from the investigations that I carried out for the issue mentioned above.
Quick refresh:
Workload: uperf sending TCP data between two VMs (client and server), each configured with a single vhost queue (min vhost ques for testing)
Issue: With lazy preemption as the default preemption mode where previously it was full preemption, there is a significant drop in performance for this workload
Simplification of the issue
We have two tasks:
TaskA produces data
TaskB consumes the data produced by TaskA
Notification path: TaskA informs TaskB that new data is available by adding a new item to a workqueue. This triggers a kworker which runs and notifies TaskB.
Issue
TaskA is configured to use schedule_work(). Internally, schedule_work() uses system_percpu_wq, which is configured as:
<WQ_PERCPU = 1 << 8, /* bound to a specific cpu */>
This means the workqueue item will be woken up and executed on the same CPU that queued the work.
If the task that queues the work (TaskA) is a long-running task with limited opportunities to call schedule(), then the kworker may be delayed significantly before it gets CPU time.
In our scenario:
TaskA continuously produces data
There is no dependency requiring TaskA to yield due to TaskB
As a result, TaskA can occupy the CPU for an entire tick before being preempted by the kworker
Observed behavior
This is exactly what we observe in practice:
TaskB corresponds to the VM consuming data generated by our vhost task
When running uperf, this behavior leads to a significant drop in throughput (Gb/s)
The VM is unable to consume data in a timely manner
When it is finally notified of new data, the delayed signaling introduces jitter
This causes TCP issues, including retransmissions and out-of-order packets
Results:
|--------------+-----+------------------+------------------------|
| preempt mode | Gbs | workqueue pool | kworker latency avg ms |
|--------------+-----+------------------+------------------------|
| full | ~50 | system_percpu_wq | 0.002 |
| lazy | ~13 | system_percpu_wq | 0.721 |
| lazy | ~50 | system_dfl_wq | 0.005 |
|--------------+-----+------------------+------------------------|
So I did some more testing and if I use a different workqueue pool the system_dfl_wq the TP was good again, as you can see in the results table.
Since the kworker is not CPU-bound, the scheduler has flexibility to select a more suitable CPU for execution.
/* system_dfl_wq is unbound workqueue. Workers are not bound to
* any specific CPU, not concurrency managed, and all queued works are
* executed immediately as long as max_active limit is not reached and
* resources are available. */
Given this understanding, what would be the best approach here? Should we consider changing the workqueue usage in the KVM code, or do you see an alternative way to address this issue?
next prev parent reply other threads:[~2026-06-05 10:44 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-19 10:15 [PATCH] sched: Further restrict the preemption modes Peter Zijlstra
2026-01-06 15:23 ` Valentin Schneider
2026-01-06 16:40 ` Steven Rostedt
2026-01-09 11:23 ` Shrikanth Hegde
2026-02-25 10:53 ` Peter Zijlstra
2026-02-25 12:56 ` Shrikanth Hegde
2026-02-26 0:48 ` Steven Rostedt
2026-02-26 5:30 ` Shrikanth Hegde
2026-02-26 17:22 ` Steven Rostedt
2026-02-27 9:09 ` Shrikanth Hegde
2026-02-27 14:53 ` Steven Rostedt
2026-02-27 15:28 ` Shrikanth Hegde
2026-03-09 9:13 ` Shrikanth Hegde
2026-01-12 8:03 ` [tip: sched/core] " tip-bot2 for Peter Zijlstra
2026-02-24 15:45 ` [PATCH] " Ciunas Bennett
2026-02-24 17:11 ` Sebastian Andrzej Siewior
2026-02-25 9:56 ` Ciunas Bennett
2026-02-25 2:30 ` Ilya Leoshkevich
2026-02-25 16:33 ` Christian Borntraeger
2026-02-25 18:30 ` Douglas Freimuth
2026-03-03 9:15 ` Ciunas Bennett
2026-03-03 11:52 ` Peter Zijlstra
2026-06-05 10:43 ` Ciunas Bennett [this message]
2026-06-05 10:52 ` Sebastian Andrzej Siewior
2026-06-05 11:01 ` Ciunas Bennett
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6c3fbb6d-d4e1-4984-b584-c067be844098@linux.ibm.com \
--to=ciunas@linux.ibm.com \
--cc=bigeasy@linutronix.de \
--cc=borntraeger@linux.ibm.com \
--cc=brueckner@linux.ibm.com \
--cc=bsegall@google.com \
--cc=clrkwllms@kernel.org \
--cc=dietmar.eggemann@arm.com \
--cc=freimuth@linux.ibm.com \
--cc=iii@linux.ibm.com \
--cc=juri.lelli@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rt-devel@lists.linux.dev \
--cc=linux-s390@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@kernel.org \
--cc=mjrosato@linux.ibm.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox