diff --git a/benchv2/Cargo.lock b/benchv2/Cargo.lock index 4a02f77..c6153ea 100644 --- a/benchv2/Cargo.lock +++ b/benchv2/Cargo.lock @@ -106,7 +106,7 @@ dependencies = [ "futures-util", "memmap2", "percent-encoding", - "rand", + "rand 0.10.3", "reqwest", "serde", "serde_json", @@ -147,6 +147,9 @@ dependencies = [ "http", "http-body-util", "hyper", + "hyper-named-pipe", + "hyper-util", + "hyperlocal", "log", "pin-project-lite", "serde", @@ -206,6 +209,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "chrono" version = "0.4.45" @@ -483,11 +497,23 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -545,6 +571,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "hybrid-array" version = "0.4.14" @@ -567,6 +599,7 @@ dependencies = [ "http", "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", "pin-utils", @@ -575,6 +608,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-named-pipe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fab3637d6b04a8037af8a266fdf6cf92ea957e8c53981a2bf6136572531025bf" +dependencies = [ + "hex", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-rustls" version = "0.27.7" @@ -615,6 +662,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "hyperlocal" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7" +dependencies = [ + "hex", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "iana-time-zone" version = "0.1.65" @@ -1030,7 +1092,7 @@ dependencies = [ "bytes", "getrandom 0.3.4", "lru-slab", - "rand", + "rand 0.9.5", "ring", "rustc-hash", "rustls", @@ -1071,14 +1133,31 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ec095654a25171c2124e9e3393a930bddbffdc939556c914957a4c3e0a87166" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" dependencies = [ "rand_chacha", - "rand_core", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core 0.10.1", ] [[package]] @@ -1088,7 +1167,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.9.5", ] [[package]] @@ -1100,6 +1179,12 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "redox_syscall" version = "0.5.18" diff --git a/benchv2/Cargo.toml b/benchv2/Cargo.toml index e521f0d..1686462 100644 --- a/benchv2/Cargo.toml +++ b/benchv2/Cargo.toml @@ -9,12 +9,12 @@ reqwest = { version = "0.12", default-features = false, features = ["json", "rus serde = { version = "1", features = ["derive"] } serde_json = "1" sha1 = "0.11" -rand = "0.9" +rand = "0.10" clap = { version = "4", features = ["derive", "env"] } chrono = { version = "0.4", features = ["serde"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -bollard = { version = "0.21", default-features = false } +bollard = { version = "0.21", default-features = false, features = ["pipe"] } anyhow = "1" dashmap = "6" percent-encoding = "2" diff --git a/benchv2/src/clients/qbittorrent.rs b/benchv2/src/clients/qbittorrent.rs index 012dd7f..7be9d84 100644 --- a/benchv2/src/clients/qbittorrent.rs +++ b/benchv2/src/clients/qbittorrent.rs @@ -48,21 +48,21 @@ impl QBittorrentClient { } // Parse temp password from container logs - use bollard::container::LogsOptions; + use bollard::query_parameters::LogsOptions; use futures_util::StreamExt; let containers = docker - .list_containers(Some(bollard::container::ListContainersOptions { - filters: std::collections::HashMap::from([( + .list_containers(Some(bollard::query_parameters::ListContainersOptions { + filters: Some(std::collections::HashMap::from([( "label".to_string(), vec!["com.docker.compose.service=qbittorrent".to_string()], - )]), + )])), ..Default::default() })) .await?; for c in containers { let id = c.id.as_deref().unwrap_or(""); - let mut log_stream = docker.logs::( + let mut log_stream = docker.logs( id, Some(LogsOptions { stdout: true, diff --git a/benchv2/src/datagen.rs b/benchv2/src/datagen.rs index 1ccce40..39d6a2c 100644 --- a/benchv2/src/datagen.rs +++ b/benchv2/src/datagen.rs @@ -24,14 +24,14 @@ fn piece_length(file_size: u64) -> u64 { pub async fn generate_test_file(path: &Path, size: u64) -> Result<()> { let path = path.to_path_buf(); task::spawn_blocking(move || { - use rand::RngCore; + use rand::Rng; use std::io::Write; if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; } let mut f = std::io::BufWriter::with_capacity(4 * MB as usize, std::fs::File::create(&path)?); - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let chunk_size = 4 * MB as usize; let mut buf = vec![0u8; chunk_size]; let mut written: u64 = 0; diff --git a/benchv2/src/docker.rs b/benchv2/src/docker.rs index d65120e..10f8a21 100644 --- a/benchv2/src/docker.rs +++ b/benchv2/src/docker.rs @@ -15,8 +15,8 @@ pub async fn get_service_ips(docker: &Docker, service: &str) -> Result Option vec![format!("com.docker.compose.service={service}")], )]); let containers = docker - .list_containers(Some(bollard::container::ListContainersOptions { - filters, + .list_containers(Some(bollard::query_parameters::ListContainersOptions { + filters: Some(filters), ..Default::default() })) .await diff --git a/benchv2/src/metrics.rs b/benchv2/src/metrics.rs index ea82f6c..3a7aa52 100644 --- a/benchv2/src/metrics.rs +++ b/benchv2/src/metrics.rs @@ -1,5 +1,5 @@ use bollard::Docker; -use bollard::container::StatsOptions; +use bollard::query_parameters::StatsOptions; use futures_util::StreamExt; use serde::Serialize; use std::collections::HashMap; @@ -40,8 +40,8 @@ impl MetricsCollector { )]); if let Ok(containers) = self .docker - .list_containers(Some(bollard::container::ListContainersOptions { - filters, + .list_containers(Some(bollard::query_parameters::ListContainersOptions { + filters: Some(filters), ..Default::default() })) .await @@ -97,43 +97,52 @@ impl MetricsCollector { .as_secs_f64(); // CPU usage: calculate percentage from cumulative counters - let cpu_total = stat.cpu_stats.cpu_usage.total_usage; - let cpu_system = stat.cpu_stats.system_cpu_usage.unwrap_or(0); - let num_cpus = stat.cpu_stats.online_cpus.unwrap_or( - stat.cpu_stats.cpu_usage.percpu_usage - .as_ref() + let cpu = stat.cpu_stats.as_ref(); + let cpu_usage = cpu.and_then(|c| c.cpu_usage.as_ref()); + let cpu_total = cpu_usage.and_then(|u| u.total_usage).unwrap_or(0); + let cpu_system = cpu.and_then(|c| c.system_cpu_usage).unwrap_or(0); + let num_cpus = cpu.and_then(|c| c.online_cpus).map(u64::from).unwrap_or( + cpu_usage + .and_then(|u| u.percpu_usage.as_ref()) .map(|v| v.len() as u64) .unwrap_or(1) ); - // Memory - let mem_bytes = stat.memory_stats.usage.unwrap_or(0) - - stat.memory_stats.stats - .as_ref() - .and_then(|s| match s { - bollard::container::MemoryStatsStats::V1(v1) => Some(v1.total_inactive_file), - bollard::container::MemoryStatsStats::V2(v2) => Some(v2.inactive_file), - }) - .unwrap_or(0); + // Memory (cgroup v1 reports total_inactive_file, v2 inactive_file) + let mem = stat.memory_stats.as_ref(); + let inactive_file = mem + .and_then(|m| m.stats.as_ref()) + .and_then(|s| s.get("total_inactive_file").or_else(|| s.get("inactive_file"))) + .copied() + .unwrap_or(0); + let mem_bytes = mem + .and_then(|m| m.usage) + .unwrap_or(0) + .saturating_sub(inactive_file); // Network (sum all interfaces) let mut net_rx: u64 = 0; let mut net_tx: u64 = 0; if let Some(networks) = &stat.networks { for net in networks.values() { - net_rx += net.rx_bytes; - net_tx += net.tx_bytes; + net_rx += net.rx_bytes.unwrap_or(0); + net_tx += net.tx_bytes.unwrap_or(0); } } // Block I/O let mut disk_read: u64 = 0; let mut disk_write: u64 = 0; - if let Some(bio) = &stat.blkio_stats.io_service_bytes_recursive { + if let Some(bio) = stat + .blkio_stats + .as_ref() + .and_then(|b| b.io_service_bytes_recursive.as_ref()) + { for entry in bio { - match entry.op.to_lowercase().as_str() { - "read" => disk_read += entry.value, - "write" => disk_write += entry.value, + let value = entry.value.unwrap_or(0); + match entry.op.as_deref().unwrap_or("").to_lowercase().as_str() { + "read" => disk_read += value, + "write" => disk_write += value, _ => {} } }