This repository has been archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Warn validators with slow hardware #12620
Merged
Merged
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
0f8dbeb
move Metric
Szegoo f232e0c
run hardware bench if validiator flag is being used
Szegoo 41c00db
fix rustdoc & update node-template
Szegoo 2a8e8df
fix
Szegoo adb5ca5
unused improt
Szegoo e16a59b
Merge branch 'paritytech:master' into warn-validators
Szegoo 2ea691d
warn
Szegoo 889e355
move Requirement
Szegoo 861ee8b
bench_result
Szegoo b3b6333
ensure_requirements
Szegoo fb5bef8
make the code compile
Szegoo befdd84
check if authority
Szegoo 355e16d
Merge branch 'paritytech:master' into warn-validators
Szegoo f79582a
Update client/sysinfo/src/sysinfo.rs
Szegoo da40db9
nit fixes
Szegoo 2b09ebe
Merge branch 'paritytech:master' into warn-validators
Szegoo b488393
warning signs
Szegoo 117663d
Update client/sysinfo/src/sysinfo.rs
Szegoo 83c7100
Merge branch 'paritytech:master' into warn-validators
Szegoo 3b28a8a
Merge branch 'paritytech:master' into warn-validators
Szegoo 400c47d
Merge branch 'paritytech:master' into warn-validators
Szegoo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,10 +21,10 @@ use crate::{ExecutionLimit, HwBench}; | |
use sc_telemetry::SysInfo; | ||
use sp_core::{sr25519, Pair}; | ||
use sp_io::crypto::sr25519_verify; | ||
use sp_std::{fmt, prelude::*}; | ||
use sp_std::{fmt, fmt::Formatter, prelude::*}; | ||
|
||
use rand::{seq::SliceRandom, Rng, RngCore}; | ||
use serde::Serializer; | ||
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; | ||
use std::{ | ||
fs::File, | ||
io::{Seek, SeekFrom, Write}, | ||
|
@@ -33,6 +33,43 @@ use std::{ | |
time::{Duration, Instant}, | ||
}; | ||
|
||
/// A single hardware metric. | ||
#[derive(Deserialize, Serialize, Debug, Clone, Copy, PartialEq)] | ||
pub enum Metric { | ||
/// SR25519 signature verification. | ||
Sr25519Verify, | ||
/// Blake2-256 hashing algorithm. | ||
Blake2256, | ||
/// Copying data in RAM. | ||
MemCopy, | ||
/// Disk sequential write. | ||
DiskSeqWrite, | ||
/// Disk random write. | ||
DiskRndWrite, | ||
} | ||
|
||
impl Metric { | ||
/// The category of the metric. | ||
pub fn category(&self) -> &'static str { | ||
match self { | ||
Self::Sr25519Verify | Self::Blake2256 => "CPU", | ||
Self::MemCopy => "Memory", | ||
Self::DiskSeqWrite | Self::DiskRndWrite => "Disk", | ||
} | ||
} | ||
|
||
/// The name of the metric. It is always prefixed by the [`self.category()`]. | ||
pub fn name(&self) -> &'static str { | ||
match self { | ||
Self::Sr25519Verify => "SR25519-Verify", | ||
Self::Blake2256 => "BLAKE2-256", | ||
Self::MemCopy => "Copy", | ||
Self::DiskSeqWrite => "Seq Write", | ||
Self::DiskRndWrite => "Rnd Write", | ||
} | ||
} | ||
} | ||
|
||
/// The unit in which the [`Throughput`] (bytes per second) is denoted. | ||
pub enum Unit { | ||
GiBs, | ||
|
@@ -137,6 +174,54 @@ where | |
serializer.serialize_none() | ||
} | ||
|
||
/// Serializes throughput into MiBs and represents it as `f64`. | ||
fn serialize_throughput_as_f64<S>(throughput: &Throughput, serializer: S) -> Result<S::Ok, S::Error> | ||
where | ||
S: Serializer, | ||
{ | ||
serializer.serialize_f64(throughput.as_mibs()) | ||
} | ||
|
||
struct ThroughputVisitor; | ||
impl<'de> Visitor<'de> for ThroughputVisitor { | ||
type Value = Throughput; | ||
|
||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { | ||
formatter.write_str("A value that is a f64.") | ||
} | ||
|
||
fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E> | ||
where | ||
E: serde::de::Error, | ||
{ | ||
Ok(Throughput::from_mibs(value)) | ||
} | ||
} | ||
|
||
fn deserialize_throughput<'de, D>(deserializer: D) -> Result<Throughput, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
Ok(deserializer.deserialize_f64(ThroughputVisitor))? | ||
} | ||
|
||
/// Multiple requirements for the hardware. | ||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] | ||
pub struct Requirements(pub Vec<Requirement>); | ||
|
||
/// A single requirement for the hardware. | ||
#[derive(Deserialize, Serialize, Debug, Clone, Copy, PartialEq)] | ||
pub struct Requirement { | ||
/// The metric to measure. | ||
pub metric: Metric, | ||
/// The minimal throughput that needs to be archived for this requirement. | ||
#[serde( | ||
serialize_with = "serialize_throughput_as_f64", | ||
deserialize_with = "deserialize_throughput" | ||
)] | ||
pub minimum: Throughput, | ||
} | ||
|
||
#[inline(always)] | ||
pub(crate) fn benchmark<E>( | ||
name: &str, | ||
|
@@ -504,7 +589,11 @@ pub fn benchmark_sr25519_verify(limit: ExecutionLimit) -> Throughput { | |
/// Benchmarks the hardware and returns the results of those benchmarks. | ||
/// | ||
/// Optionally accepts a path to a `scratch_directory` to use to benchmark the disk. | ||
pub fn gather_hwbench(scratch_directory: Option<&Path>) -> HwBench { | ||
pub fn gather_hwbench( | ||
Szegoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
scratch_directory: Option<&Path>, | ||
requirements: Requirements, | ||
is_authority: bool, | ||
) -> HwBench { | ||
#[allow(unused_mut)] | ||
let mut hwbench = HwBench { | ||
cpu_hashrate_score: benchmark_cpu(DEFAULT_CPU_EXECUTION_LIMIT), | ||
|
@@ -534,9 +623,45 @@ pub fn gather_hwbench(scratch_directory: Option<&Path>) -> HwBench { | |
}; | ||
} | ||
|
||
if is_authority { | ||
ensure_requirements(hwbench.clone(), requirements); | ||
} | ||
|
||
hwbench | ||
} | ||
|
||
fn ensure_requirements(hwbench: HwBench, requirements: Requirements) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also slightly bad that we have the logic here again, but I think its okay. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function could just have been made public and return a bool. Everybody could then build its own logic. |
||
let mut failed = 0; | ||
for requirement in requirements.0.iter() { | ||
match requirement.metric { | ||
Metric::Blake2256 => | ||
if requirement.minimum > hwbench.cpu_hashrate_score { | ||
failed += 1; | ||
}, | ||
Metric::MemCopy => | ||
if requirement.minimum > hwbench.memory_memcpy_score { | ||
failed += 1; | ||
}, | ||
Metric::DiskSeqWrite => | ||
if let Some(score) = hwbench.disk_sequential_write_score { | ||
if requirement.minimum > score { | ||
failed += 1; | ||
} | ||
}, | ||
Metric::DiskRndWrite => | ||
if let Some(score) = hwbench.disk_random_write_score { | ||
if requirement.minimum > score { | ||
failed += 1; | ||
} | ||
}, | ||
_ => (), | ||
Szegoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
if failed != 0 { | ||
log::warn!("The hardware fails to meet the requirements"); | ||
Szegoo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a bit unfortunate that we have to pass this in twice now; once for the sysinfo and once for the machine benchmarking.
But I dont see how it could be done better.