| 1 | SCHED_EXT EXAMPLE SCHEDULERS
|
| 2 | ============================
|
| 3 |
|
| 4 | # Introduction
|
| 5 |
|
| 6 | This directory contains a number of example sched_ext schedulers. These
|
| 7 | schedulers are meant to provide examples of different types of schedulers
|
| 8 | that can be built using sched_ext, and illustrate how various features of
|
| 9 | sched_ext can be used.
|
| 10 |
|
| 11 | Some of the examples are performant, production-ready schedulers. That is, for
|
| 12 | the correct workload and with the correct tuning, they may be deployed in a
|
| 13 | production environment with acceptable or possibly even improved performance.
|
| 14 | Others are just examples that in practice, would not provide acceptable
|
| 15 | performance (though they could be improved to get there).
|
| 16 |
|
| 17 | This README will describe these example schedulers, including describing the
|
| 18 | types of workloads or scenarios they're designed to accommodate, and whether or
|
| 19 | not they're production ready. For more details on any of these schedulers,
|
| 20 | please see the header comment in their .bpf.c file.
|
| 21 |
|
| 22 |
|
| 23 | # Compiling the examples
|
| 24 |
|
| 25 | There are a few toolchain dependencies for compiling the example schedulers.
|
| 26 |
|
| 27 | ## Toolchain dependencies
|
| 28 |
|
| 29 | 1. clang >= 16.0.0
|
| 30 |
|
| 31 | The schedulers are BPF programs, and therefore must be compiled with clang. gcc
|
| 32 | is actively working on adding a BPF backend compiler as well, but are still
|
| 33 | missing some features such as BTF type tags which are necessary for using
|
| 34 | kptrs.
|
| 35 |
|
| 36 | 2. pahole >= 1.25
|
| 37 |
|
| 38 | You may need pahole in order to generate BTF from DWARF.
|
| 39 |
|
| 40 | 3. rust >= 1.70.0
|
| 41 |
|
| 42 | Rust schedulers uses features present in the rust toolchain >= 1.70.0. You
|
| 43 | should be able to use the stable build from rustup, but if that doesn't
|
| 44 | work, try using the rustup nightly build.
|
| 45 |
|
| 46 | There are other requirements as well, such as make, but these are the main /
|
| 47 | non-trivial ones.
|
| 48 |
|
| 49 | ## Compiling the kernel
|
| 50 |
|
| 51 | In order to run a sched_ext scheduler, you'll have to run a kernel compiled
|
| 52 | with the patches in this repository, and with a minimum set of necessary
|
| 53 | Kconfig options:
|
| 54 |
|
| 55 | ```
|
| 56 | CONFIG_BPF=y
|
| 57 | CONFIG_SCHED_CLASS_EXT=y
|
| 58 | CONFIG_BPF_SYSCALL=y
|
| 59 | CONFIG_BPF_JIT=y
|
| 60 | CONFIG_DEBUG_INFO_BTF=y
|
| 61 | CONFIG_BPF_JIT_ALWAYS_ON=y
|
| 62 | CONFIG_BPF_JIT_DEFAULT_ON=y
|
| 63 | ```
|
| 64 |
|
| 65 | There is a `Kconfig` file in this directory whose contents you can append to
|
| 66 | your local `.config` file, as long as there are no conflicts with any existing
|
| 67 | options in the file.
|
| 68 |
|
| 69 | ## Getting a vmlinux.h file
|
| 70 |
|
| 71 | You may notice that most of the example schedulers include a "vmlinux.h" file.
|
| 72 | This is a large, auto-generated header file that contains all of the types
|
| 73 | defined in some vmlinux binary that was compiled with
|
| 74 | [BTF](https://docs.kernel.org/bpf/btf.html) (i.e. with the BTF-related Kconfig
|
| 75 | options specified above).
|
| 76 |
|
| 77 | The header file is created using `bpftool`, by passing it a vmlinux binary
|
| 78 | compiled with BTF as follows:
|
| 79 |
|
| 80 | ```bash
|
| 81 | $ bpftool btf dump file /path/to/vmlinux format c > vmlinux.h
|
| 82 | ```
|
| 83 |
|
| 84 | `bpftool` analyzes all of the BTF encodings in the binary, and produces a
|
| 85 | header file that can be included by BPF programs to access those types. For
|
| 86 | example, using vmlinux.h allows a scheduler to access fields defined directly
|
| 87 | in vmlinux as follows:
|
| 88 |
|
| 89 | ```c
|
| 90 | #include "vmlinux.h"
|
| 91 | // vmlinux.h is also implicitly included by scx_common.bpf.h.
|
| 92 | #include "scx_common.bpf.h"
|
| 93 |
|
| 94 | /*
|
| 95 | * vmlinux.h provides definitions for struct task_struct and
|
| 96 | * struct scx_enable_args.
|
| 97 | */
|
| 98 | void BPF_STRUCT_OPS(example_enable, struct task_struct *p,
|
| 99 | struct scx_enable_args *args)
|
| 100 | {
|
| 101 | bpf_printk("Task %s enabled in example scheduler", p->comm);
|
| 102 | }
|
| 103 |
|
| 104 | // vmlinux.h provides the definition for struct sched_ext_ops.
|
| 105 | SEC(".struct_ops.link")
|
| 106 | struct sched_ext_ops example_ops {
|
| 107 | .enable = (void *)example_enable,
|
| 108 | .name = "example",
|
| 109 | }
|
| 110 | ```
|
| 111 |
|
| 112 | The scheduler build system will generate this vmlinux.h file as part of the
|
| 113 | scheduler build pipeline. It looks for a vmlinux file in the following
|
| 114 | dependency order:
|
| 115 |
|
| 116 | 1. If the O= environment variable is defined, at `$O/vmlinux`
|
| 117 | 2. If the KBUILD_OUTPUT= environment variable is defined, at
|
| 118 | `$KBUILD_OUTPUT/vmlinux`
|
| 119 | 3. At `../../vmlinux` (i.e. at the root of the kernel tree where you're
|
| 120 | compiling the schedulers)
|
| 121 | 3. `/sys/kernel/btf/vmlinux`
|
| 122 | 4. `/boot/vmlinux-$(uname -r)`
|
| 123 |
|
| 124 | In other words, if you have compiled a kernel in your local repo, its vmlinux
|
| 125 | file will be used to generate vmlinux.h. Otherwise, it will be the vmlinux of
|
| 126 | the kernel you're currently running on. This means that if you're running on a
|
| 127 | kernel with sched_ext support, you may not need to compile a local kernel at
|
| 128 | all.
|
| 129 |
|
| 130 | ### Aside on CO-RE
|
| 131 |
|
| 132 | One of the cooler features of BPF is that it supports
|
| 133 | [CO-RE](https://nakryiko.com/posts/bpf-core-reference-guide/) (Compile Once Run
|
| 134 | Everywhere). This feature allows you to reference fields inside of structs with
|
| 135 | types defined internal to the kernel, and not have to recompile if you load the
|
| 136 | BPF program on a different kernel with the field at a different offset. In our
|
| 137 | example above, we print out a task name with `p->comm`. CO-RE would perform
|
| 138 | relocations for that access when the program is loaded to ensure that it's
|
| 139 | referencing the correct offset for the currently running kernel.
|
| 140 |
|
| 141 | ## Compiling the schedulers
|
| 142 |
|
| 143 | Once you have your toolchain setup, and a vmlinux that can be used to generate
|
| 144 | a full vmlinux.h file, you can compile the schedulers using `make`:
|
| 145 |
|
| 146 | ```bash
|
| 147 | $ make -j($nproc)
|
| 148 | ```
|
| 149 |
|
| 150 | # Example schedulers
|
| 151 |
|
| 152 | This directory contains the following example schedulers. These schedulers are
|
| 153 | for testing and demonstrating different aspects of sched_ext. While some may be
|
| 154 | useful in limited scenarios, they are not intended to be practical.
|
| 155 |
|
| 156 | For more scheduler implementations, tools and documentation, visit
|
| 157 | https://github.com/sched-ext/scx.
|
| 158 |
|
| 159 | ## scx_simple
|
| 160 |
|
| 161 | A simple scheduler that provides an example of a minimal sched_ext scheduler.
|
| 162 | scx_simple can be run in either global weighted vtime mode, or FIFO mode.
|
| 163 |
|
| 164 | Though very simple, in limited scenarios, this scheduler can perform reasonably
|
| 165 | well on single-socket systems with a unified L3 cache.
|
| 166 |
|
| 167 | ## scx_qmap
|
| 168 |
|
| 169 | Another simple, yet slightly more complex scheduler that provides an example of
|
| 170 | a basic weighted FIFO queuing policy. It also provides examples of some common
|
| 171 | useful BPF features, such as arena-backed doubly-linked lists threaded through
|
| 172 | per-task context and `bpf_res_spin_lock` for per-queue synchronization. It also
|
| 173 | illustrates how core-sched support could be implemented.
|
| 174 |
|
| 175 | ## scx_central
|
| 176 |
|
| 177 | A "central" scheduler where scheduling decisions are made from a single CPU.
|
| 178 | This scheduler illustrates how scheduling decisions can be dispatched from a
|
| 179 | single CPU, allowing other cores to run with infinite slices, without timer
|
| 180 | ticks, and without having to incur the overhead of making scheduling decisions.
|
| 181 |
|
| 182 | The approach demonstrated by this scheduler may be useful for any workload that
|
| 183 | benefits from minimizing scheduling overhead and timer ticks. An example of
|
| 184 | where this could be particularly useful is running VMs, where running with
|
| 185 | infinite slices and no timer ticks allows the VM to avoid unnecessary expensive
|
| 186 | vmexits.
|
| 187 |
|
| 188 | ## scx_flatcg
|
| 189 |
|
| 190 | A flattened cgroup hierarchy scheduler. This scheduler implements hierarchical
|
| 191 | weight-based cgroup CPU control by flattening the cgroup hierarchy into a single
|
| 192 | layer, by compounding the active weight share at each level. The effect of this
|
| 193 | is a much more performant CPU controller, which does not need to descend down
|
| 194 | cgroup trees in order to properly compute a cgroup's share.
|
| 195 |
|
| 196 | Similar to scx_simple, in limited scenarios, this scheduler can perform
|
| 197 | reasonably well on single socket-socket systems with a unified L3 cache and show
|
| 198 | significantly lowered hierarchical scheduling overhead.
|
| 199 |
|
| 200 |
|
| 201 | # Troubleshooting
|
| 202 |
|
| 203 | There are a number of common issues that you may run into when building the
|
| 204 | schedulers. We'll go over some of the common ones here.
|
| 205 |
|
| 206 | ## Build Failures
|
| 207 |
|
| 208 | ### Old version of clang
|
| 209 |
|
| 210 | ```
|
| 211 | error: static assertion failed due to requirement 'SCX_DSQ_FLAG_BUILTIN': bpftool generated vmlinux.h is missing high bits for 64bit enums, upgrade clang and pahole
|
| 212 | _Static_assert(SCX_DSQ_FLAG_BUILTIN,
|
| 213 | ^~~~~~~~~~~~~~~~~~~~
|
| 214 | 1 error generated.
|
| 215 | ```
|
| 216 |
|
| 217 | This means you built the kernel or the schedulers with an older version of
|
| 218 | clang than what's supported (i.e. older than 16.0.0). To remediate this:
|
| 219 |
|
| 220 | 1. `which clang` to make sure you're using a sufficiently new version of clang.
|
| 221 |
|
| 222 | 2. `make fullclean` in the root path of the repository, and rebuild the kernel
|
| 223 | and schedulers.
|
| 224 |
|
| 225 | 3. Rebuild the kernel, and then your example schedulers.
|
| 226 |
|
| 227 | The schedulers are also cleaned if you invoke `make mrproper` in the root
|
| 228 | directory of the tree.
|
| 229 |
|
| 230 | ### Stale kernel build / incomplete vmlinux.h file
|
| 231 |
|
| 232 | As described above, you'll need a `vmlinux.h` file that was generated from a
|
| 233 | vmlinux built with BTF, and with sched_ext support enabled. If you don't,
|
| 234 | you'll see errors such as the following which indicate that a type being
|
| 235 | referenced in a scheduler is unknown:
|
| 236 |
|
| 237 | ```
|
| 238 | /path/to/sched_ext/tools/sched_ext/user_exit_info.h:25:23: note: forward declaration of 'struct scx_exit_info'
|
| 239 |
|
| 240 | const struct scx_exit_info *ei)
|
| 241 |
|
| 242 | ^
|
| 243 | ```
|
| 244 |
|
| 245 | In order to resolve this, please follow the steps above in
|
| 246 | [Getting a vmlinux.h file](#getting-a-vmlinuxh-file) in order to ensure your
|
| 247 | schedulers are using a vmlinux.h file that includes the requisite types.
|
| 248 |
|
| 249 | ## Misc
|
| 250 |
|
| 251 | ### llvm: [OFF]
|
| 252 |
|
| 253 | You may see the following output when building the schedulers:
|
| 254 |
|
| 255 | ```
|
| 256 | Auto-detecting system features:
|
| 257 | ... clang-bpf-co-re: [ on ]
|
| 258 | ... llvm: [ OFF ]
|
| 259 | ... libcap: [ on ]
|
| 260 | ... libbfd: [ on ]
|
| 261 | ```
|
| 262 |
|
| 263 | Seeing `llvm: [ OFF ]` here is not an issue. You can safely ignore.
|