Skip to content
This repository has been archived by the owner on Jun 18, 2024. It is now read-only.

Commit

Permalink
sched_ext: Add scx_layered, a highly configurable multi-layer scheduler
Browse files Browse the repository at this point in the history
scx_layered allows classifying tasks into multiple layers and applying
different scheduling policies to them. The configuration is specified in
json and composed of two parts - matches and policies.

The matches classify tasks into a layer and different scheduling policies
can be applied to the layer. For example, if a layer is "Confined", its
tasks are confined to the CPUs that are allocated to the layer. The CPU
allocation is dynamically adjusted to target CPU utilization in a specific
range. This can be used to e.g. confine managerial workloads to a small
number of CPUs while leaving the rest for latency sensitive workloads. A
layer can also be configured to preempt other non-preempting layers.

This scheduler is limited in that it assumes homogenous CPUs in a single
node and the load based CPU allocation limit doesn't work well yet. However,
even in the current form, in an experimental deployment over ~1000 machines,
it showed a significant (>5%) bandwidth gain with a large-scale latency
sensitive workload.

As sched_ext scheduler development style and cadence are different from
kernel proper, the plan is to keep simpler example schedulers and one more
generic scheduler (scx_rusty) in tree and publish others in a separate
repository. This scheduler will be a part of that repo once ready.

NOT_FOR_UPSTREAM_INCLUSION
  • Loading branch information
htejun committed Nov 14, 2023
1 parent d295467 commit 597552f
Show file tree
Hide file tree
Showing 10 changed files with 2,912 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tools/sched_ext/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ $(c-sched-targets): %: $(BINDIR)/%
###################
# Rust schedulers #
###################
rust-sched-targets := scx_rusty
rust-sched-targets := scx_rusty scx_layered

# Separate build target that is available for build systems to use to fetch
# dependencies in a separate step from building. This allows the scheduler
Expand Down
3 changes: 3 additions & 0 deletions tools/sched_ext/scx_layered/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src/bpf/.output
Cargo.lock
target
30 changes: 30 additions & 0 deletions tools/sched_ext/scx_layered/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "scx_layered"
version = "0.0.1"
authors = ["Tejun Heo <[email protected]>", "Meta"]
edition = "2021"
description = "Userspace scheduling with BPF for Ads"
license = "GPL-2.0-only"

[dependencies]
anyhow = "1.0"
bitvec = "1.0"
clap = { version = "4.1", features = ["derive", "env", "unicode", "wrap_help"] }
ctrlc = { version = "3.1", features = ["termination"] }
fb_procfs = "0.7"
lazy_static = "1.4"
libbpf-rs = "0.21"
libbpf-sys = { version = "1.2.0", features = ["novendor", "static"] }
libc = "0.2"
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
simplelog = "0.12"

[build-dependencies]
bindgen = { version = "0.61" }
libbpf-cargo = "0.21"
glob = "0.3"

[features]
enable_backtrace = []
77 changes: 77 additions & 0 deletions tools/sched_ext/scx_layered/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Meta Platforms, Inc. and affiliates.

// This software may be used and distributed according to the terms of the
// GNU General Public License version 2.
extern crate bindgen;

use std::env;
use std::fs::create_dir_all;
use std::path::Path;
use std::path::PathBuf;

use glob::glob;
use libbpf_cargo::SkeletonBuilder;

const HEADER_PATH: &str = "src/bpf/layered.h";

fn bindgen_layered() {
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed={}", HEADER_PATH);

// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header(HEADER_PATH)
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");

// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("layered_sys.rs"))
.expect("Couldn't write bindings!");
}

fn gen_bpf_sched(name: &str) {
let bpf_cflags = env::var("SCX_RUST_BPF_CFLAGS").unwrap();
let clang = env::var("SCX_RUST_CLANG").unwrap();
eprintln!("{}", clang);
let outpath = format!("./src/bpf/.output/{}.skel.rs", name);
let skel = Path::new(&outpath);
let src = format!("./src/bpf/{}.bpf.c", name);
let obj = format!("./src/bpf/.output/{}.bpf.o", name);
SkeletonBuilder::new()
.source(src.clone())
.obj(obj)
.clang(clang)
.clang_args(bpf_cflags)
.build_and_generate(skel)
.unwrap();

// Trigger rebuild if any .[hc] files are changed in the directory.
for path in glob("./src/bpf/*.[hc]").unwrap().filter_map(Result::ok) {
println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}
}

fn main() {
bindgen_layered();
// It's unfortunate we cannot use `OUT_DIR` to store the generated skeleton.
// Reasons are because the generated skeleton contains compiler attributes
// that cannot be `include!()`ed via macro. And we cannot use the `#[path = "..."]`
// trick either because you cannot yet `concat!(env!("OUT_DIR"), "/skel.rs")` inside
// the path attribute either (see https://github.com/rust-lang/rust/pull/83366).
//
// However, there is hope! When the above feature stabilizes we can clean this
// all up.
create_dir_all("./src/bpf/.output").unwrap();
gen_bpf_sched("layered");
}
8 changes: 8 additions & 0 deletions tools/sched_ext/scx_layered/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Get help on options with `rustfmt --help=config`
# Please keep these in alphabetical order.
edition = "2021"
group_imports = "StdExternalCrate"
imports_granularity = "Item"
merge_derives = false
use_field_init_shorthand = true
version = "Two"
Loading

0 comments on commit 597552f

Please sign in to comment.