From ca1ac8aec85e356377e554e6ad28142ff2e65c6e Mon Sep 17 00:00:00 2001 From: iximeow Date: Tue, 4 Jul 2023 14:51:07 -0700 Subject: try reporting max cpu freq, but this is going to be messy --- src/ci_runner.rs | 27 +++++++++++++++++++++++++-- src/dbctx.rs | 22 +++++++++++++--------- src/main.rs | 12 +++++++----- src/protocol.rs | 2 ++ src/sql.rs | 1 + 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/ci_runner.rs b/src/ci_runner.rs index 3e7dd42..63dc74e 100644 --- a/src/ci_runner.rs +++ b/src/ci_runner.rs @@ -545,6 +545,27 @@ mod host_info { .to_string() } + /// try finding core `cpu`'s max frequency in khz. we'll assume this is the actual speed a + /// build would run at.. fingers crossed. + fn try_finding_cpu_freq(cpu: u32) -> Result { + if let Ok(freq_str) = std::fs::read_to_string("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq") { + Ok(freq_str.trim().parse().unwrap()) + } else { + // so cpufreq probably isn't around, maybe /proc/cpuinfo's mhz figure is present? + let cpu_lines: Vec = std::fs::read_to_string("/proc/cpuinfo").unwrap().split("\n").map(|line| line.to_string()).collect(); + let cpu_mhzes: Vec<&String> = cpu_lines.iter().filter(|line| line.starts_with("cpu MHz")).collect(); + match cpu_mhzes.get(cpu as usize) { + Some(mhz) => { + let mhz: f64 = cpu_mhzes[cpu as usize].trim().parse().unwrap(); + Ok((mhz * 1000.0) as u64) + }, + None => { + panic!("could not get cpu freq either from cpufreq or /proc/cpuinfo?"); + } + } + } + } + // we'll have to deploy one of a few techniques, because x86/x86_64 is internally // consistent, but aarch64 is different. who knows what other CPUs think. match std::env::consts::ARCH { @@ -557,8 +578,9 @@ mod host_info { let family = find_line(&cpu_lines, "cpu family"); let model = find_line(&cpu_lines, "model\t"); let microcode = find_line(&cpu_lines, "microcode"); + let max_freq = try_finding_cpu_freq(0).unwrap(); - CpuInfo { model_name, microcode, cores, vendor_id, family, model } + CpuInfo { model_name, microcode, cores, vendor_id, family, model, max_freq } } "aarch64" => { let cpu_lines: Vec = std::fs::read_to_string("/proc/cpuinfo").unwrap().split("\n").map(|line| line.to_string()).collect(); @@ -588,8 +610,9 @@ mod host_info { let family = find_line(&cpu_lines, "CPU architecture"); let model = find_line(&cpu_lines, "CPU part"); let microcode = String::new(); + let max_freq = std::fs::read_to_string("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq").unwrap().trim().parse().unwrap(); - CpuInfo { model_name, microcode, cores, vendor_id: vendor_name, family, model } + CpuInfo { model_name, microcode, cores, vendor_id: vendor_name, family, model, max_freq } } other => { panic!("dunno how to find cpu info for {}, panik", other); diff --git a/src/dbctx.rs b/src/dbctx.rs index 3fa65e8..f5f900a 100644 --- a/src/dbctx.rs +++ b/src/dbctx.rs @@ -592,14 +592,15 @@ impl DbCtx { .query_row( "select id from hosts where \ hostname=?1 and cpu_vendor_id=?2 and cpu_model_name=?3 and cpu_family=?4 and \ - cpu_model=?5 and cpu_cores=?6 and mem_total=?7 and \ - arch=?10);", + cpu_model=?5 and cpu_max_freq_khz=?6 and cpu_cores=?7 and mem_total=?8 and \ + arch=?9);", ( &host_info.hostname, &host_info.cpu_info.vendor_id, &host_info.cpu_info.model_name, &host_info.cpu_info.family, &host_info.cpu_info.model, + &host_info.cpu_info.max_freq, &host_info.cpu_info.cores, &host_info.memory_info.total, &host_info.env_info.arch, @@ -619,12 +620,12 @@ impl DbCtx { "insert or ignore into hosts \ (\ hostname, cpu_vendor_id, cpu_model_name, cpu_family, \ - cpu_model, cpu_microcode, cpu_cores, mem_total, \ - arch, family, os\ + cpu_model, cpu_microcode, cpu_max_freq_khz, cpu_cores, \ + mem_total, arch, family, os\ ) values (\ ?1, ?2, ?3, ?4, \ ?5, ?6, ?7, ?8, \ - ?9, ?10, ?11 \ + ?9, ?10, ?11, ?12 \ );", ( &host_info.hostname, @@ -633,6 +634,7 @@ impl DbCtx { &host_info.cpu_info.family, &host_info.cpu_info.model, &host_info.cpu_info.microcode, + &host_info.cpu_info.max_freq, &host_info.cpu_info.cores, &host_info.memory_info.total, &host_info.env_info.arch, @@ -646,8 +648,8 @@ impl DbCtx { .query_row( "select id from hosts where \ hostname=?1 and cpu_vendor_id=?2 and cpu_model_name=?3 and cpu_family=?4 and \ - cpu_model=?5 and cpu_microcode=?6 and cpu_cores=?7 and mem_total=?8 and \ - arch=?9 and family=?10 and os=?11;", + cpu_model=?5 and cpu_microcode=?6 and cpu_max_freq_khz=?7 and \ + cpu_cores=?8 and mem_total=?9 and arch=?10 and family=?11 and os=?12;", ( &host_info.hostname, &host_info.cpu_info.vendor_id, @@ -655,6 +657,7 @@ impl DbCtx { &host_info.cpu_info.family, &host_info.cpu_info.model, &host_info.cpu_info.microcode, + &host_info.cpu_info.max_freq, &host_info.cpu_info.cores, &host_info.memory_info.total, &host_info.env_info.arch, @@ -666,15 +669,16 @@ impl DbCtx { .map_err(|e| e.to_string()) } - pub fn host_model_info(&self, host_id: u64) -> Result<(String, String, String, String), String> { + pub fn host_model_info(&self, host_id: u64) -> Result<(String, String, String, String, u64), String> { let conn = self.conn.lock().unwrap(); conn - .query_row("select hostname, cpu_vendor_id, cpu_family, cpu_model from hosts where id=?1;", [host_id], |row| { + .query_row("select hostname, cpu_vendor_id, cpu_family, cpu_model, cpu_max_freq_khz from hosts where id=?1;", [host_id], |row| { Ok(( row.get(0).unwrap(), row.get(1).unwrap(), row.get(2).unwrap(), row.get(3).unwrap(), + row.get(4).unwrap(), )) }) .map_err(|e| e.to_string()) diff --git a/src/main.rs b/src/main.rs index 2658e9d..d11df1f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -680,16 +680,16 @@ fn summarize_job_metrics(dbctx: &Arc, run_id: u64, job_id: u64) -> Result metrics_map.insert(metric.name, metric.value); } - let (hostname, cpu_vendor_id, cpu_family, cpu_model) = match run.host_id { + let (hostname, cpu_vendor_id, cpu_family, cpu_model, cpu_max_freq_khz) = match run.host_id { Some(host_id) => { dbctx.host_model_info(host_id).unwrap() } None => { - ("unknown".to_string(), "unknown".to_string(), "0".to_string(), "0".to_string()) + ("unknown".to_string(), "unknown".to_string(), "0".to_string(), "0".to_string(), 0) } }; - (metrics_map, HostDesc::from_parts(hostname, cpu_vendor_id, cpu_family, cpu_model)) + (metrics_map, HostDesc::from_parts(hostname, cpu_vendor_id, cpu_family, cpu_model, cpu_max_freq_khz)) }).collect(); if all_metrics.is_empty() { @@ -698,7 +698,7 @@ fn summarize_job_metrics(dbctx: &Arc, run_id: u64, job_id: u64) -> Result let mut header = "name".to_string(); for (_, host) in all_metrics.iter() { - header.push_str(&format!("{} - {}", &host.hostname, &host.cpu_desc)); + header.push_str(&format!("{}
{} @ {:.3}GHz", &host.hostname, &host.cpu_desc, (host.cpu_max_freq_khz as f64) / 1000_000.0)); } header.push_str("\n"); section.push_str(&header); @@ -1072,9 +1072,10 @@ async fn main() { struct HostDesc { hostname: String, cpu_desc: String, + cpu_max_freq_khz: u64, } impl HostDesc { - fn from_parts(hostname: String, vendor_id: String, cpu_family: String, model: String) -> Self { + fn from_parts(hostname: String, vendor_id: String, cpu_family: String, model: String, cpu_max_freq_khz: u64) -> Self { let cpu_desc = match (vendor_id.as_str(), cpu_family.as_str(), model.as_str()) { ("Arm Limited", "8", "0xd03") => "aarch64 A53".to_string(), ("GenuineIntel", "6", "85") => "x86_64 Skylake".to_string(), @@ -1085,6 +1086,7 @@ impl HostDesc { HostDesc { hostname, cpu_desc, + cpu_max_freq_khz, } } } diff --git a/src/protocol.rs b/src/protocol.rs index d7193e4..c7a9318 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -89,6 +89,8 @@ pub struct CpuInfo { pub vendor_id: String, pub family: String, pub model: String, + // clock speed in khz + pub max_freq: u64, } #[derive(Serialize, Deserialize, Debug, Clone)] diff --git a/src/sql.rs b/src/sql.rs index 34bc8aa..e98c111 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -125,6 +125,7 @@ pub const CREATE_HOSTS_TABLE: &'static str = "\ cpu_family TEXT, cpu_model TEXT, cpu_microcode TEXT, + cpu_max_freq_khz INTEGER, cpu_cores INTEGER, mem_total TEXT, arch TEXT, -- cgit v1.1