mirror of
https://github.com/sched-ext/scx.git
synced 2024-11-28 05:30:24 +00:00
scx_loader: Add initial automatic scheduler switching via --monitor-no-dbus
Exposes an option --monitor-no-dbus in scx_loader that will monitor CPU utilization and start scx_lavd when any CPU exceeds 90% for more than 5 seconds. scx_lavd will be terminated if all CPUs are below 90% for more than 30 seconds. When this flag is specified, scx_loader's dbus functionality is not utilized.
This commit is contained in:
parent
ad8536b4a4
commit
d434ab4266
99
Cargo.lock
generated
99
Cargo.lock
generated
@ -953,7 +953,7 @@ dependencies = [
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
"windows-core 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1247,6 +1247,15 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@ -1546,6 +1555,26 @@ dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.3"
|
||||
@ -1714,6 +1743,7 @@ dependencies = [
|
||||
"log",
|
||||
"nix 0.29.0",
|
||||
"serde",
|
||||
"sysinfo",
|
||||
"tokio",
|
||||
"zbus",
|
||||
"zvariant",
|
||||
@ -2038,6 +2068,20 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.31.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
"memchr",
|
||||
"ntapi",
|
||||
"rayon",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.1"
|
||||
@ -2442,6 +2486,16 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
|
||||
dependencies = [
|
||||
"windows-core 0.57.0",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
@ -2451,6 +2505,49 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.57.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
@ -14,6 +14,7 @@ ctrlc = { version = "3.1", features = ["termination"] }
|
||||
log = "0.4.17"
|
||||
nix = { features = ["process", "signal"], default-features = false, version = "0.29" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sysinfo = "0.31.4"
|
||||
tokio = { version = "1.39", features = ["macros", "sync", "rt-multi-thread", "process"] }
|
||||
zbus = { version = "4", features = ["tokio"], default-features = false }
|
||||
zvariant = "4.2"
|
||||
|
@ -23,6 +23,9 @@ use zbus::interface;
|
||||
use zbus::Connection;
|
||||
use zvariant::Type;
|
||||
use zvariant::Value;
|
||||
use clap::Parser;
|
||||
use sysinfo::{System};
|
||||
use std::{process::{Child}, time::{Duration, Instant}, thread};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum SupportedSched {
|
||||
@ -63,6 +66,13 @@ struct ScxLoader {
|
||||
channel: UnboundedSender<ScxMessage>,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[clap(long, short, action)]
|
||||
monitor_no_dbus: bool,
|
||||
}
|
||||
|
||||
#[interface(name = "org.scx.Loader")]
|
||||
impl ScxLoader {
|
||||
/// Get currently running scheduler, in case non is running return "unknown"
|
||||
@ -139,11 +149,73 @@ impl ScxLoader {
|
||||
}
|
||||
}
|
||||
|
||||
// Monitors CPU utilization and enables scx_lavd when utilization of any CPUs is > 90%
|
||||
async fn monitor_cpu_util() -> Result<()> {
|
||||
let mut system = System::new_all();
|
||||
let mut running_sched: Option<Child> = None;
|
||||
let mut cpu_above_threshold_since: Option<Instant> = None;
|
||||
let mut cpu_below_threshold_since: Option<Instant> = None;
|
||||
|
||||
let high_utilization_threshold = 90.0;
|
||||
let low_utilization_threshold_duration = Duration::from_secs(30);
|
||||
let high_utilization_trigger_duration = Duration::from_secs(5);
|
||||
|
||||
loop {
|
||||
system.refresh_cpu_all();
|
||||
|
||||
let any_cpu_above_threshold = system.cpus().iter().any(|cpu| cpu.cpu_usage() > high_utilization_threshold);
|
||||
|
||||
if any_cpu_above_threshold {
|
||||
if cpu_above_threshold_since.is_none() {
|
||||
cpu_above_threshold_since = Some(Instant::now());
|
||||
}
|
||||
|
||||
if cpu_above_threshold_since.unwrap().elapsed() > high_utilization_trigger_duration {
|
||||
if running_sched.is_none() {
|
||||
println!("CPU Utilization exceeded 90% for 5 seconds, starting scx_lavd");
|
||||
running_sched = Some(std::process::Command::new("scx_lavd").spawn().expect("Failed to start scx_lavd"));
|
||||
}
|
||||
|
||||
cpu_below_threshold_since = None;
|
||||
}
|
||||
} else {
|
||||
cpu_above_threshold_since = None;
|
||||
|
||||
if cpu_below_threshold_since.is_none() {
|
||||
cpu_below_threshold_since = Some(Instant::now());
|
||||
}
|
||||
|
||||
if cpu_below_threshold_since.unwrap().elapsed() > low_utilization_threshold_duration {
|
||||
if let Some(mut running_sched_loc) = running_sched.take() {
|
||||
println!("CPU utilization dropped below 90% for more than 30 seconds, exiting latency-aware scheduler");
|
||||
running_sched_loc.kill().expect("Failed to kill scx_lavd");
|
||||
let lavd_exit_status = running_sched_loc.wait().expect("Failed to wait on scx_lavd");
|
||||
println!("scx_lavd exited with status: {}", lavd_exit_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// initialize the logger
|
||||
logger::init_logger().expect("Failed to initialize logger");
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
// If --monitor_no_dbus is passed, start scx_loader as a standard background process
|
||||
// that swaps schedulers out automatically
|
||||
// based on CPU utilization without registering a dbus interface.
|
||||
if args.monitor_no_dbus {
|
||||
println!("Starting scx_loader monitor as standard process without dbus interface");
|
||||
monitor_cpu_util().await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
println!("Starting as dbus interface");
|
||||
// setup channel
|
||||
let (channel, rx) = tokio::sync::mpsc::unbounded_channel::<ScxMessage>();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user