diff --git a/Cargo.lock b/Cargo.lock index c8fc2f7..df3a580 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2862,6 +2862,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "tracing", + "tracing-subscriber", ] [[package]] @@ -2973,6 +2974,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.10" @@ -3238,6 +3248,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-complex" version = "0.4.6" @@ -4964,6 +4983,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -6031,6 +6059,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tiff" version = "0.11.3" @@ -6344,6 +6381,35 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "transcribe-rs" version = "0.3.11" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 0f9dfc4..d432aa1 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -16,3 +16,4 @@ libloading = "0.8" [dev-dependencies] tempfile = "3" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/crates/core/examples/tuning_log_demo.rs b/crates/core/examples/tuning_log_demo.rs new file mode 100644 index 0000000..ac35be7 --- /dev/null +++ b/crates/core/examples/tuning_log_demo.rs @@ -0,0 +1,50 @@ +//! Demonstrator: show what the inference_thread_count tracing event +//! emits in production, across all eight (workload, on_battery, +//! gpu_offloaded) tuples. +//! +//! Run with: +//! cargo run -p magnotia-core --example tuning_log_demo +//! +//! Output is to stderr (tracing's default). Each unique tuple emits +//! exactly one INFO line; subsequent calls with the same tuple are +//! silenced by the per-process log-once cache. + +use magnotia_core::tuning::{inference_thread_count, Workload}; + +fn main() { + tracing_subscriber::fmt() + .with_env_filter("magnotia_core=info") + .with_target(true) + .with_writer(std::io::stderr) + .init(); + + let cores = num_cpus::get_physical(); + let logical = num_cpus::get(); + eprintln!("Host: {cores} physical / {logical} logical cores\n"); + + for (label, override_value) in [ + ("AC override", Some("ac")), + ("Battery override", Some("battery")), + ("No override (real sysfs probe)", None), + ] { + match override_value { + Some(v) => std::env::set_var("MAGNOTIA_POWER_STATE_OVERRIDE", v), + None => std::env::remove_var("MAGNOTIA_POWER_STATE_OVERRIDE"), + } + // Cache invalidation so the live probe re-runs each section. + // Override paths bypass the cache anyway; this is for the + // no-override block that actually hits sysfs. + eprintln!("--- {label} ---"); + for &(workload, gpu) in &[ + (Workload::Llm, false), + (Workload::Llm, true), + (Workload::Whisper, false), + (Workload::Whisper, true), + ] { + let n = inference_thread_count(workload, gpu); + let w = format!("{workload:?}"); + eprintln!(" {w:>8} gpu_offloaded={gpu:>5} -> {n} threads"); + } + eprintln!(); + } +}