Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

substrate: sysinfo: Expose failed hardware requirements #2144

Merged
merged 1 commit into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions cumulus/parachain-template/node/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,14 @@ async fn start_node_impl(
// Here you can check whether the hardware meets your chains' requirements. Putting a link
// in there and swapping out the requirements for your own are probably a good idea. The
// requirements for a para-chain are dictated by its relay-chain.
if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && validator {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements for role 'Authority'."
match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) {
Err(err) if validator => {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'.",
err
);
},
_ => {},
}

if let Some(ref mut telemetry) = telemetry {
Expand Down
7 changes: 4 additions & 3 deletions cumulus/polkadot-parachain/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1955,10 +1955,11 @@ pub async fn start_contracts_rococo_node(
fn warn_if_slow_hardware(hwbench: &sc_sysinfo::HwBench) {
// Polkadot para-chains should generally use these requirements to ensure that the relay-chain
// will not take longer than expected to import its blocks.
if !frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE.check_hardware(hwbench) {
if let Err(err) = frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE.check_hardware(hwbench) {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements for role 'Authority' find out more at:\n\
https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware"
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority' find out more at:\n\
https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware",
err
);
}
}
12 changes: 8 additions & 4 deletions polkadot/node/service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -965,11 +965,15 @@ pub fn new_full<OverseerGenerator: OverseerGen>(

if let Some(hwbench) = hwbench {
sc_sysinfo::print_hwbench(&hwbench);
if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && role.is_authority() {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements for role 'Authority' find out more at:\n\
https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware"
match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) {
Err(err) if role.is_authority() => {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority' find out more at:\n\
https://wiki.polkadot.network/docs/maintain-guides-how-to-validate-polkadot#reference-hardware",
err
);
},
_ => {},
}

if let Some(ref mut telemetry) = telemetry {
Expand Down
12 changes: 8 additions & 4 deletions substrate/bin/node/cli/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,10 +449,14 @@ pub fn new_full_base(

if let Some(hwbench) = hwbench {
sc_sysinfo::print_hwbench(&hwbench);
if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && role.is_authority() {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements for role 'Authority'."
);
match SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) {
Err(err) if role.is_authority() => {
log::warn!(
"⚠️ The hardware does not meet the minimal requirements {} for role 'Authority'.",
err
);
},
_ => {},
}

if let Some(ref mut telemetry) = telemetry {
Expand Down
1 change: 1 addition & 0 deletions substrate/client/sysinfo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ libc = "0.2"
log = "0.4.17"
rand = "0.8.5"
rand_pcg = "0.3.1"
derive_more = "0.99"
regex = "1"
serde = { version = "1.0.188", features = ["derive"] }
serde_json = "1.0.107"
Expand Down
66 changes: 60 additions & 6 deletions substrate/client/sysinfo/src/sysinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ use sp_core::{sr25519, Pair};
use sp_io::crypto::sr25519_verify;
use sp_std::{fmt, fmt::Formatter, prelude::*};

use derive_more::From;
use rand::{seq::SliceRandom, Rng, RngCore};
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::Display,
fs::File,
io::{Seek, SeekFrom, Write},
ops::{Deref, DerefMut},
Expand All @@ -48,6 +50,37 @@ pub enum Metric {
DiskRndWrite,
}

/// Describes a checking failure for the hardware requirements.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CheckFailure {
/// The metric that failed the check.
pub metric: Metric,
/// The expected minimum value.
pub expected: Throughput,
/// The measured value.
pub found: Throughput,
}

/// A list of metrics that failed to meet the minimum hardware requirements.
#[derive(Debug, Clone, PartialEq, From)]
pub struct CheckFailures(pub Vec<CheckFailure>);

impl Display for CheckFailures {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "Failed checks: ")?;
for failure in &self.0 {
write!(
formatter,
"{}(expected: {}, found: {}), ",
failure.metric.name(),
failure.expected,
failure.found
)?
}
Ok(())
}
}

impl Metric {
/// The category of the metric.
pub fn category(&self) -> &'static str {
Expand Down Expand Up @@ -626,33 +659,54 @@ pub fn gather_hwbench(scratch_directory: Option<&Path>) -> HwBench {

impl Requirements {
/// Whether the hardware requirements are met by the provided benchmark results.
pub fn check_hardware(&self, hwbench: &HwBench) -> bool {
pub fn check_hardware(&self, hwbench: &HwBench) -> Result<(), CheckFailures> {
let mut failures = Vec::new();
for requirement in self.0.iter() {
match requirement.metric {
Metric::Blake2256 =>
if requirement.minimum > hwbench.cpu_hashrate_score {
return false
failures.push(CheckFailure {
metric: requirement.metric,
expected: requirement.minimum,
found: hwbench.cpu_hashrate_score,
});
},
Metric::MemCopy =>
if requirement.minimum > hwbench.memory_memcpy_score {
return false
failures.push(CheckFailure {
metric: requirement.metric,
expected: requirement.minimum,
found: hwbench.memory_memcpy_score,
});
},
Metric::DiskSeqWrite =>
if let Some(score) = hwbench.disk_sequential_write_score {
if requirement.minimum > score {
return false
failures.push(CheckFailure {
metric: requirement.metric,
expected: requirement.minimum,
found: score,
});
}
},
Metric::DiskRndWrite =>
if let Some(score) = hwbench.disk_random_write_score {
if requirement.minimum > score {
return false
failures.push(CheckFailure {
metric: requirement.metric,
expected: requirement.minimum,
found: score,
});
}
},
Metric::Sr25519Verify => {},
}
}
true
if failures.is_empty() {
Ok(())
} else {
Err(failures.into())
}
}
}

Expand Down
Loading