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 1.6k
cli: introduce host-perf-check command #4342
Merged
Merged
Changes from 10 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
d21db4e
cli: introduce host-perf-check command
slumber 5937ce6
fix build
slumber ff6d3a1
Review fixes
slumber 71b19d3
Extract perf check into new module
slumber 6770d63
Explicit log level
slumber e142424
Use a build script for cfg build
slumber 9414d2f
Save dummy file in HOME
slumber c6a72a8
Refactor
slumber a4f75a2
Error on any non-release build
slumber 65701ad
Improve naming
slumber 30e225f
Use the base path for caching
slumber 7bb37a2
Reuse wasm binary from kusama_runtime
slumber 11f1a16
Update cli/src/command.rs
slumber a2b0a72
Add an explanation to gethostname
slumber 2aba480
Make cache path configurable
slumber 2891597
Add erasure-coding check
slumber a39de72
Green threshold for perf tests
slumber f89e6b5
Write hostname without zero bytes
slumber 4dd4e89
Add force flag
slumber de88f4c
Extract performance test into a separate crate
slumber 95bf838
Implement constants generation
slumber 633088d
Add logs
slumber 28ecac3
Simplify fs read/write
slumber ab46e65
Propagate tracing error
slumber 04d311e
Expect instead of unwrap
slumber f9ae107
Update headers
slumber f8739ae
Rename cache_path to base_path
slumber 9bdbddd
Drop caching
slumber f36888d
Apply suggestions from code review
bkchr e1e42e4
Merge remote-tracking branch 'origin/master' into slumber-hostperfche…
slumber 66dfa6d
Decrease the number of warm up runs
slumber 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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 |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// 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 polkadot_node_core_pvf::sc_executor_common; | ||
use std::time::Duration; | ||
|
||
#[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)] | ||
PerfCheck(#[from] PerfCheckError), | ||
|
||
#[error("Other: {0}")] | ||
Other(String), | ||
} | ||
|
||
#[allow(missing_docs)] | ||
#[derive(thiserror::Error, Debug)] | ||
pub enum PerfCheckError { | ||
#[error("This subcommand is only available in release mode")] | ||
WrongBuildType, | ||
|
||
#[error("Failed to decompress wasm code")] | ||
CodeDecompressionFailed, | ||
|
||
#[error(transparent)] | ||
Wasm(#[from] sc_executor_common::error::WasmError), | ||
|
||
#[error( | ||
"Performance check not passed: exceeded the {limit:?} time limit, elapsed: {elapsed:?}" | ||
)] | ||
TimeOut { elapsed: Duration, limit: Duration }, | ||
} | ||
drahnr marked this conversation as resolved.
Show resolved
Hide resolved
|
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 |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// 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 crate::error::PerfCheckError; | ||
use log::info; | ||
use nix::unistd; | ||
use polkadot_node_core_pvf::sp_maybe_compressed_blob; | ||
use std::{ | ||
fs::{self, OpenOptions}, | ||
io::{self, Read, Write}, | ||
path::{Path, PathBuf}, | ||
time::{Duration, Instant}, | ||
}; | ||
|
||
fn check_passed_file_path() -> io::Result<PathBuf> { | ||
let home_dir = | ||
std::env::var("HOME").map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; | ||
slumber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let path = Path::new(&home_dir).join(".polkadot"); | ||
|
||
if let Err(err) = fs::create_dir(&path) { | ||
if err.kind() != io::ErrorKind::AlreadyExists { | ||
return Err(err) | ||
} | ||
} | ||
|
||
Ok(path.join("perf_check_passed")) | ||
} | ||
|
||
fn is_perf_check_done(path: &Path) -> io::Result<bool> { | ||
let host_name_max_len = unistd::SysconfVar::HOST_NAME_MAX as usize; | ||
|
||
let mut host_name = vec![0u8; host_name_max_len]; | ||
let mut buf = host_name.clone(); | ||
unistd::gethostname(&mut host_name).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; | ||
|
||
let file = match fs::File::open(path) { | ||
Ok(file) => file, | ||
Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(false), | ||
Err(err) => return Err(err), | ||
}; | ||
let mut reader = io::BufReader::new(file); | ||
|
||
reader.read_exact(&mut buf)?; | ||
slumber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Ok(host_name == buf) | ||
} | ||
|
||
fn save_check_passed_file(path: &Path) -> io::Result<()> { | ||
let host_name_max_len = unistd::SysconfVar::HOST_NAME_MAX as usize; | ||
let mut host_name = vec![0u8; host_name_max_len]; | ||
unistd::gethostname(&mut host_name).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; | ||
drahnr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let mut file = OpenOptions::new().truncate(true).create(true).write(true).open(path)?; | ||
|
||
file.write(&host_name)?; | ||
|
||
Ok(()) | ||
slumber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
pub fn host_perf_check() -> Result<(), PerfCheckError> { | ||
const PERF_CHECK_TIME_LIMIT: Duration = Duration::from_secs(20); | ||
const CODE_SIZE_LIMIT: usize = 1024usize.pow(3); | ||
const WASM_CODE: &[u8] = include_bytes!( | ||
"../../target/release/wbuild/kusama-runtime/kusama_runtime.compact.compressed.wasm" | ||
slumber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
|
||
// We will try to save a special file at $HOME/.polkadot/perf_check_passed. | ||
let check_passed_path = check_passed_file_path() | ||
.map_err(|err| { | ||
info!( | ||
"Performance check result is not going to be persisted due to an error: {:?}", | ||
err | ||
) | ||
}) | ||
.ok(); | ||
|
||
if let Some(ref path) = check_passed_path { | ||
if let Ok(true) = is_perf_check_done(path) { | ||
info!("Performance check skipped: already passed"); | ||
return Ok(()) | ||
} | ||
} | ||
|
||
info!("Running the performance check..."); | ||
let start = Instant::now(); | ||
|
||
// Recreate the pipeline from the pvf prepare worker. | ||
let code = sp_maybe_compressed_blob::decompress(WASM_CODE, CODE_SIZE_LIMIT) | ||
.or(Err(PerfCheckError::CodeDecompressionFailed))?; | ||
let blob = polkadot_node_core_pvf::prevalidate(code.as_ref()).map_err(PerfCheckError::from)?; | ||
let _ = polkadot_node_core_pvf::prepare(blob).map_err(PerfCheckError::from)?; | ||
|
||
let elapsed = start.elapsed(); | ||
if elapsed <= PERF_CHECK_TIME_LIMIT { | ||
info!("Performance check passed, elapsed: {:?}", start.elapsed()); | ||
slumber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Persist successful result. | ||
check_passed_path.map(|path| save_check_passed_file(&path)); | ||
Ok(()) | ||
} else { | ||
Err(PerfCheckError::TimeOut { elapsed, limit: PERF_CHECK_TIME_LIMIT }) | ||
} | ||
} |
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.
will this work with custom profiles #4311 (comment) @bkchr?
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.
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.