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