Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scheds: Introduce scx_tickless #1446

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

scheds: Introduce scx_tickless #1446

wants to merge 1 commit into from

Conversation

arighi
Copy link
Contributor

@arighi arighi commented Mar 2, 2025

scx_tickless is a server-oriented scheduler, derived from scx_central, designed to minimize OS noise and maximize performance isolation.

The scheduler works by routing all scheduling events through a pool of primary CPUs assigned to handle these events. This allows disabling the scheduler's tick on other CPUs, reducing OS noise.

Tasks are added to a global DSQ, and the primary CPUs distribute them across the other "tickless" CPUs, sending preemption events via IPC in case multiple tasks are competing for the same CPU.

In situations where the system is not overcommitted, tasks can run uninterrupted on their assigned CPUs, leading to better performance isolation and lower OS noise.

Typical use cases include cloud computing, virtualization and high performance computing workloads. This scheduler is not designed for latency-sensitive workloads.

NOTE: in order to effectively disable ticks on the "tickless" CPUs the kernel must be booted with nohz_full.

Example:

  • start a VM running a CPU-intensive workload:
   $ vng -vr -- stress-ng -c 0
  • on the host measure the rate of sched_tick events/sec:
   $ bpftrace -e 'kprobe:sched_tick { @ticks++; } interval:s:1 { print(@ticks); clear(@ticks); }'

With the default scheduler:

 @ticks: 1027
 @ticks: 1021
 @ticks: 1016
 @ticks: 1016
 @ticks: 1029
 @ticks: 1024
 @ticks: 1015
 @ticks: 1022
 @ticks: 1014
 @ticks: 1056
 ...

With scx_tickless:

 @ticks: 1000
 @ticks: 1001
 @ticks: 1001
 @ticks: 1000
 @ticks: 1001
 @ticks: 1000
 @ticks: 1000
 @ticks: 1002
 @ticks: 1000
 @ticks: 1000
 ...

@arighi arighi requested review from htejun, multics69 and hodgesds March 2, 2025 09:51
Copy link
Contributor

@multics69 multics69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code mixes scx_bpf_now() and bpf_ktime_get_ns()., Is this intentional?

@arighi
Copy link
Contributor Author

arighi commented Mar 2, 2025

The code mixes scx_bpf_now() and bpf_ktime_get_ns()., Is this intentional?

Nope, I'll fix that, thanks for catching it!

scx_tickless is a server-oriented scheduler, derived from scx_central,
designed to minimize OS noise and maximize performance isolation.

The scheduler works by routing all scheduling events through a pool of
primary CPUs assigned to handle these events. This allows disabling the
scheduler's tick on other CPUs, reducing OS noise.

Tasks are added to a global DSQ, and the primary CPUs distribute them
across the other "tickless" CPUs, sending preemption events via IPC in
case multiple tasks are competing for the same CPU.

In situations where the system is not overcommitted, tasks can run
uninterrupted on their assigned CPUs, leading to better performance
isolation and lower OS noise.

Typical use cases include cloud computing, virtualization and high
performance computing workloads. This scheduler is *not* designed for
latency-sensitive workloads.

NOTE: in order to effectively disable ticks on the "tickless" CPUs the
kernel must be booted with nohz_full.

Example:

 - start a VM running a CPU-intensive workload:

   $ vng -vr -- stress-ng -c 0

 - on the host measure the rate of sched_tick events/sec:

   $ bpftrace -e 'kprobe:sched_tick { @ticks++; } interval:s:1 { print(@ticks); clear(@ticks); }'

With the default scheduler:
 @ticks: 1027
 @ticks: 1021
 @ticks: 1016
 @ticks: 1016
 @ticks: 1029
 @ticks: 1024
 @ticks: 1015
 @ticks: 1022
 @ticks: 1014
 @ticks: 1056
 ...

With scx_tickless:
 @ticks: 1000
 @ticks: 1001
 @ticks: 1001
 @ticks: 1000
 @ticks: 1001
 @ticks: 1000
 @ticks: 1000
 @ticks: 1002
 @ticks: 1000
 @ticks: 1000
 ...

Signed-off-by: Andrea Righi <[email protected]>
bool dispatched = false;

bpf_for_each(scx_dsq, p, SHARED_DSQ, 0) {
p = bpf_task_from_pid(p->pid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment explaining that this is working around a BPF issue and isn't needed on newer kernels?

* non-primary CPUs were busy and a task was dispatched
* there.
*/
scx_bpf_kick_cpu(pick_primary_cpu(), SCX_KICK_PREEMPT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be cheaper for !primary cpu to dispatch directly if it's about to go idle anyway?

!scx_bpf_dsq_nr_queued(SHARED_DSQ))
continue;

scx_bpf_kick_cpu(cpu, SCX_KICK_PREEMPT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be possible to call dispatch_all_cpus() directly from the timer.

Copy link
Contributor

@sirlucjan sirlucjan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to add

Tested-by: Piotr Gorski [email protected]

@sirlucjan
Copy link
Contributor

sirlucjan commented Mar 3, 2025

@arighi Is there any chance that before the next stable release we will add this to scx_loader? Or does it not make sense in your opinion?

@arighi
Copy link
Contributor Author

arighi commented Mar 3, 2025

@sirlucjan sure, I'll add the change to include it in scx_loader in this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants