Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

cli: introduce host-perf-check command #4342

Merged
merged 31 commits into from
Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d21db4e
cli: introduce host-perf-check command
slumber Nov 21, 2021
5937ce6
fix build
slumber Nov 22, 2021
ff6d3a1
Review fixes
slumber Nov 22, 2021
71b19d3
Extract perf check into new module
slumber Nov 23, 2021
6770d63
Explicit log level
slumber Nov 23, 2021
e142424
Use a build script for cfg build
slumber Nov 23, 2021
9414d2f
Save dummy file in HOME
slumber Nov 23, 2021
c6a72a8
Refactor
slumber Nov 24, 2021
a4f75a2
Error on any non-release build
slumber Nov 24, 2021
65701ad
Improve naming
slumber Nov 24, 2021
30e225f
Use the base path for caching
slumber Nov 24, 2021
7bb37a2
Reuse wasm binary from kusama_runtime
slumber Nov 24, 2021
11f1a16
Update cli/src/command.rs
slumber Nov 25, 2021
a2b0a72
Add an explanation to gethostname
slumber Nov 25, 2021
2aba480
Make cache path configurable
slumber Nov 30, 2021
2891597
Add erasure-coding check
slumber Dec 1, 2021
a39de72
Green threshold for perf tests
slumber Dec 1, 2021
f89e6b5
Write hostname without zero bytes
slumber Dec 2, 2021
4dd4e89
Add force flag
slumber Dec 2, 2021
de88f4c
Extract performance test into a separate crate
slumber Dec 3, 2021
95bf838
Implement constants generation
slumber Dec 3, 2021
633088d
Add logs
slumber Dec 3, 2021
28ecac3
Simplify fs read/write
slumber Dec 4, 2021
ab46e65
Propagate tracing error
slumber Dec 4, 2021
04d311e
Expect instead of unwrap
slumber Dec 4, 2021
f9ae107
Update headers
slumber Dec 4, 2021
f8739ae
Rename cache_path to base_path
slumber Dec 5, 2021
9bdbddd
Drop caching
slumber Dec 5, 2021
f36888d
Apply suggestions from code review
bkchr Dec 5, 2021
e1e42e4
Merge remote-tracking branch 'origin/master' into slumber-hostperfche…
slumber Dec 9, 2021
66dfa6d
Decrease the number of warm up runs
slumber Dec 9, 2021
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
16 changes: 16 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ members = [
"node/metrics",
"node/metered-channel",
"node/test/client",
"node/test/performance-test",
"node/test/service",
"node/test/polkadot-simnet/common",
"node/test/polkadot-simnet/node",
Expand Down
4 changes: 4 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ futures = "0.3.17"

service = { package = "polkadot-service", path = "../node/service", default-features = false, optional = true }
polkadot-node-core-pvf = { path = "../node/core/pvf", optional = true }
polkadot-performance-test = { path = "../node/test/performance-test", optional = true }

sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master", optional = true }

# this crate is used only to enable `trie-memory-tracker` feature
# see https://github.com/paritytech/substrate/pull/6745
Expand All @@ -43,9 +45,11 @@ cli = [
"structopt",
"sc-cli",
"sc-service",
"sc-tracing",
"frame-benchmarking-cli",
"try-runtime-cli",
"polkadot-node-core-pvf",
"polkadot-performance-test",
]
runtime-benchmarks = [ "service/runtime-benchmarks" ]
trie-memory-tracker = [ "sp-trie/memory-tracker" ]
Expand Down
5 changes: 4 additions & 1 deletion cli/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
Expand All @@ -15,5 +15,8 @@
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

fn main() {
if let Ok(profile) = std::env::var("PROFILE") {
println!("cargo:rustc-cfg=build_type=\"{}\"", profile);
}
substrate_build_script_utils::generate_cargo_keys();
}
4 changes: 4 additions & 0 deletions cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ pub enum Subcommand {
#[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
Benchmark(frame_benchmarking_cli::BenchmarkCmd),

/// Runs performance checks such as PVF compilation in order to measure machine
/// capabilities of running a validator.
HostPerfCheck,

/// Try some command against runtime state.
#[cfg(feature = "try-runtime")]
TryRuntime(try_runtime_cli::TryRuntimeCmd),
Expand Down
37 changes: 23 additions & 14 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,8 @@ use sc_cli::{Role, RuntimeVersion, SubstrateCli};
use service::{self, IdentifyVariant};
use sp_core::crypto::Ss58AddressFormatRegistry;

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
PolkadotService(#[from] service::Error),

#[error(transparent)]
SubstrateCli(#[from] sc_cli::Error),

#[error(transparent)]
SubstrateService(#[from] sc_service::Error),

#[error("Other: {0}")]
Other(String),
}
pub use crate::error::Error;
pub use polkadot_performance_test::PerfCheckError;

impl std::convert::From<String> for Error {
fn from(s: String) -> Self {
Expand Down Expand Up @@ -215,6 +203,20 @@ fn ensure_dev(spec: &Box<dyn service::ChainSpec>) -> std::result::Result<(), Str
}
}

/// Runs performance checks.
/// Should only be used in release build since the check would take too much time otherwise.
fn host_perf_check() -> Result<()> {
#[cfg(not(build_type = "release"))]
{
Err(PerfCheckError::WrongBuildType.into())
}
#[cfg(build_type = "release")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this work with custom profiles #4311 (comment) @bkchr?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, the profile should be matched with the one used for distributing the binary. If this profile changes to e.g release-lto, it should be also updated here.

{
crate::host_perf_check::host_perf_check()?;
Ok(())
}
}

/// Launch a node, accepting arguments just like a regular node,
/// accepts an alternative overseer generator, to adjust behavior
/// for integration tests as needed.
Expand Down Expand Up @@ -415,6 +417,13 @@ pub fn run() -> Result<()> {
#[cfg(not(feature = "polkadot-native"))]
panic!("No runtime feature (polkadot, kusama, westend, rococo) is enabled")
},
Some(Subcommand::HostPerfCheck) => {
let mut builder = sc_cli::LoggerBuilder::new("");
slumber marked this conversation as resolved.
Show resolved Hide resolved
builder.with_colors(true);
builder.init()?;

host_perf_check()
},
Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
#[cfg(feature = "try-runtime")]
Some(Subcommand::TryRuntime(cmd)) => {
Expand Down
36 changes: 36 additions & 0 deletions cli/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
PolkadotService(#[from] service::Error),

#[error(transparent)]
SubstrateCli(#[from] sc_cli::Error),

#[error(transparent)]
SubstrateService(#[from] sc_service::Error),

#[error(transparent)]
SubstrateTracing(#[from] sc_tracing::logging::Error),

#[error(transparent)]
PerfCheck(#[from] polkadot_performance_test::PerfCheckError),

#[error("Other: {0}")]
Other(String),
}
drahnr marked this conversation as resolved.
Show resolved Hide resolved
67 changes: 67 additions & 0 deletions cli/src/host_perf_check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use log::info;
use polkadot_node_core_pvf::sp_maybe_compressed_blob;
use polkadot_performance_test::{
measure_erasure_coding, measure_pvf_prepare, PerfCheckError, ERASURE_CODING_N_VALIDATORS,
ERASURE_CODING_TIME_LIMIT, PVF_PREPARE_TIME_LIMIT, VALIDATION_CODE_BOMB_LIMIT,
};
use std::time::Duration;

pub fn host_perf_check() -> Result<(), PerfCheckError> {
let wasm_code =
polkadot_performance_test::WASM_BINARY.ok_or(PerfCheckError::WasmBinaryMissing)?;

// Decompress the code before running checks.
let code = sp_maybe_compressed_blob::decompress(wasm_code, VALIDATION_CODE_BOMB_LIMIT)
.or(Err(PerfCheckError::CodeDecompressionFailed))?;

info!("Running the performance checks...");

perf_check("PVF-prepare", PVF_PREPARE_TIME_LIMIT, || measure_pvf_prepare(code.as_ref()))?;

perf_check("Erasure-coding", ERASURE_CODING_TIME_LIMIT, || {
measure_erasure_coding(ERASURE_CODING_N_VALIDATORS, code.as_ref())
})?;

Ok(())
}

fn green_threshold(duration: Duration) -> Duration {
duration * 4 / 5
}

fn perf_check(
test_name: &str,
time_limit: Duration,
test: impl Fn() -> Result<Duration, PerfCheckError>,
) -> Result<(), PerfCheckError> {
let elapsed = test()?;

if elapsed < green_threshold(time_limit) {
info!("🟢 {} performance check passed, elapsed: {:?}", test_name, elapsed);
Ok(())
} else if elapsed <= time_limit {
info!(
"🟡 {} performance check passed, {:?} limit almost exceeded, elapsed: {:?}",
test_name, time_limit, elapsed
);
Ok(())
} else {
Err(PerfCheckError::TimeOut { elapsed, limit: time_limit })
}
}
4 changes: 4 additions & 0 deletions cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
mod cli;
#[cfg(feature = "cli")]
mod command;
#[cfg(feature = "cli")]
mod error;
#[cfg(all(feature = "cli", build_type = "release"))]
mod host_perf_check;

#[cfg(feature = "full-node")]
pub use service::RuntimeApiCollection;
Expand Down
4 changes: 2 additions & 2 deletions erasure-coding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ pub fn obtain_chunks_v1(n_validators: usize, data: &AvailableData) -> Result<Vec
/// Obtain erasure-coded chunks, one for each validator.
///
/// Works only up to 65536 validators, and `n_validators` must be non-zero.
fn obtain_chunks<T: Encode>(n_validators: usize, data: &T) -> Result<Vec<Vec<u8>>, Error> {
pub fn obtain_chunks<T: Encode>(n_validators: usize, data: &T) -> Result<Vec<Vec<u8>>, Error> {
let params = code_params(n_validators)?;
let encoded = data.encode();

Expand Down Expand Up @@ -186,7 +186,7 @@ where
/// are provided, recovery is not possible.
///
/// Works only up to 65536 validators, and `n_validators` must be non-zero.
fn reconstruct<'a, I: 'a, T: Decode>(n_validators: usize, chunks: I) -> Result<T, Error>
pub fn reconstruct<'a, I: 'a, T: Decode>(n_validators: usize, chunks: I) -> Result<T, Error>
where
I: IntoIterator<Item = (&'a [u8], usize)>,
{
Expand Down
5 changes: 5 additions & 0 deletions node/core/pvf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,9 @@ pub use metrics::Metrics;
pub use execute::worker_entrypoint as execute_worker_entrypoint;
pub use prepare::worker_entrypoint as prepare_worker_entrypoint;

pub use executor_intf::{prepare, prevalidate};

pub use sc_executor_common;
pub use sp_maybe_compressed_blob;

const LOG_TARGET: &str = "parachain::pvf";
21 changes: 21 additions & 0 deletions node/test/performance-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "polkadot-performance-test"
version = "0.9.13"
authors = ["Parity Technologies <[email protected]>"]
edition = "2018"

[dependencies]
thiserror = "1.0.30"
quote = "1.0.10"
env_logger = "0.9"
log = "0.4"

polkadot-node-core-pvf = { path = "../../core/pvf" }
polkadot-erasure-coding = { path = "../../../erasure-coding" }
polkadot-node-primitives = { path = "../../primitives" }

kusama-runtime = { path = "../../../runtime/kusama" }

[[bin]]
name = "gen-ref-constants"
path = "src/gen_ref_constants.rs"
21 changes: 21 additions & 0 deletions node/test/performance-test/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

fn main() {
if let Ok(profile) = std::env::var("PROFILE") {
println!("cargo:rustc-cfg=build_type=\"{}\"", profile);
}
}
22 changes: 22 additions & 0 deletions node/test/performance-test/src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2017-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

//! This file was automatically generated by `gen-ref-constants`.
//! Do not edit manually!

use std::time::Duration;
pub const PVF_PREPARE_TIME_LIMIT: Duration = Duration::from_millis(4910u64);
pub const ERASURE_CODING_TIME_LIMIT: Duration = Duration::from_millis(466u64);
Loading