soil_service/sysinfo/
mod.rs1use futures::prelude::*;
11use std::time::Duration;
12
13mod sysinfo;
14#[cfg(target_os = "freebsd")]
15mod sysinfo_freebsd;
16#[cfg(target_os = "linux")]
17mod sysinfo_linux;
18
19pub use sysinfo::{
20 benchmark_cpu, benchmark_cpu_parallelism, benchmark_disk_random_writes,
21 benchmark_disk_sequential_writes, benchmark_memory, benchmark_sr25519_verify, gather_hwbench,
22 gather_sysinfo, serialize_throughput, serialize_throughput_option, Metric, Requirement,
23 Requirements, Throughput, SUBSTRATE_REFERENCE_HARDWARE,
24};
25
26pub const TARGET_OS: &str = include_str!(concat!(env!("OUT_DIR"), "/target_os.txt"));
28
29pub const TARGET_ARCH: &str = include_str!(concat!(env!("OUT_DIR"), "/target_arch.txt"));
31
32pub const TARGET_ENV: &str = include_str!(concat!(env!("OUT_DIR"), "/target_env.txt"));
34
35#[derive(Clone, Debug, serde::Serialize)]
37pub struct HwBench {
38 #[serde(serialize_with = "serialize_throughput")]
40 pub cpu_hashrate_score: Throughput,
41 #[serde(serialize_with = "serialize_throughput")]
44 pub parallel_cpu_hashrate_score: Throughput,
45 pub parallel_cpu_cores: usize,
47 #[serde(serialize_with = "serialize_throughput")]
49 pub memory_memcpy_score: Throughput,
50 #[serde(
52 serialize_with = "serialize_throughput_option",
53 skip_serializing_if = "Option::is_none"
54 )]
55 pub disk_sequential_write_score: Option<Throughput>,
56 #[serde(
58 serialize_with = "serialize_throughput_option",
59 skip_serializing_if = "Option::is_none"
60 )]
61 pub disk_random_write_score: Option<Throughput>,
62}
63
64#[derive(Copy, Clone, Debug)]
65pub enum ExecutionLimit {
67 MaxDuration(Duration),
69
70 MaxIterations(usize),
72
73 Both { max_iterations: usize, max_duration: Duration },
75}
76
77impl ExecutionLimit {
78 pub fn from_secs_f32(secs: f32) -> Self {
80 Self::MaxDuration(Duration::from_secs_f32(secs))
81 }
82
83 pub fn max_duration(&self) -> Duration {
85 match self {
86 Self::MaxDuration(d) => *d,
87 Self::Both { max_duration, .. } => *max_duration,
88 _ => Duration::from_secs(u64::MAX),
89 }
90 }
91
92 pub fn max_iterations(&self) -> usize {
94 match self {
95 Self::MaxIterations(d) => *d,
96 Self::Both { max_iterations, .. } => *max_iterations,
97 _ => usize::MAX,
98 }
99 }
100}
101
102pub fn print_sysinfo(sysinfo: &soil_telemetry::SysInfo) {
104 log::info!("💻 Operating system: {}", TARGET_OS);
105 log::info!("💻 CPU architecture: {}", TARGET_ARCH);
106 if !TARGET_ENV.is_empty() {
107 log::info!("💻 Target environment: {}", TARGET_ENV);
108 }
109
110 if let Some(ref cpu) = sysinfo.cpu {
111 log::info!("💻 CPU: {}", cpu);
112 }
113 if let Some(core_count) = sysinfo.core_count {
114 log::info!("💻 CPU cores: {}", core_count);
115 }
116 if let Some(memory) = sysinfo.memory {
117 log::info!("💻 Memory: {}MB", memory / (1024 * 1024));
118 }
119 if let Some(ref linux_kernel) = sysinfo.linux_kernel {
120 log::info!("💻 Kernel: {}", linux_kernel);
121 }
122 if let Some(ref linux_distro) = sysinfo.linux_distro {
123 log::info!("💻 Linux distribution: {}", linux_distro);
124 }
125 if let Some(is_virtual_machine) = sysinfo.is_virtual_machine {
126 log::info!("💻 Virtual machine: {}", if is_virtual_machine { "yes" } else { "no" });
127 }
128}
129
130pub fn print_hwbench(hwbench: &HwBench) {
132 log::info!(
133 "🏁 CPU single core score: {}, parallelism score: {} with expected cores: {}",
134 hwbench.cpu_hashrate_score,
135 hwbench.parallel_cpu_hashrate_score,
136 hwbench.parallel_cpu_cores,
137 );
138 log::info!("🏁 Memory score: {}", hwbench.memory_memcpy_score);
139
140 if let Some(score) = hwbench.disk_sequential_write_score {
141 log::info!("🏁 Disk score (seq. writes): {}", score);
142 }
143 if let Some(score) = hwbench.disk_random_write_score {
144 log::info!("🏁 Disk score (rand. writes): {}", score);
145 }
146}
147
148pub fn initialize_hwbench_telemetry(
150 telemetry_handle: soil_telemetry::TelemetryHandle,
151 hwbench: HwBench,
152) -> impl std::future::Future<Output = ()> {
153 let mut connect_stream = telemetry_handle.on_connect_stream();
154 async move {
155 let payload = serde_json::to_value(&hwbench)
156 .expect("the `HwBench` can always be serialized into a JSON object; qed");
157 let mut payload = match payload {
158 serde_json::Value::Object(map) => map,
159 _ => unreachable!("the `HwBench` always serializes into a JSON object; qed"),
160 };
161 payload.insert("msg".into(), "sysinfo.hwbench".into());
162 while connect_stream.next().await.is_some() {
163 telemetry_handle.send_telemetry(soil_telemetry::SUBSTRATE_INFO, payload.clone());
164 }
165 }
166}