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

Make block benchmark #1569

Merged
merged 19 commits into from
May 4, 2023
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Changes from review
  • Loading branch information
Harrm committed Apr 24, 2023
commit 90323211d4f02a1799fdedc3bccea1bf24b9c6ea
76 changes: 44 additions & 32 deletions core/application/impl/app_configuration_impl.cpp
Original file line number Diff line number Diff line change
@@ -719,11 +719,30 @@ namespace kagome::application {
return telemetry::TelemetryEndpoint{std::move(uri), verbosity_level};
}

bool AppConfigurationImpl::initializeFromArgs(int argc,
const char **argv,
Command command) {
bool AppConfigurationImpl::initializeFromArgs(int argc, const char **argv) {
namespace po = boost::program_options;

std::optional<std::string> command;
std::optional<std::string> subcommand;

using std::string_view_literals::operator""sv;

if (argc > 0 && argv[0] == "benchmark"sv) {
command = "benchmark";

if (argc > 1 && argv[1] == "block"sv) {
subcommand = "block";
} else {
SL_ERROR(logger_, "Usage: kagome benchmark BENCHMARK_TYPE");
SL_ERROR(logger_, "The only supported BENCHMARK_TYPE is 'block'");
return false;
}
}
if (subcommand) {
argc--;
argv++;
}
Comment on lines +757 to +760
Copy link
Contributor

Choose a reason for hiding this comment

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

Should command remove first arg too?


// clang-format off
po::options_description desc("General options");
desc.add_options()
@@ -824,9 +843,12 @@ namespace kagome::application {
desc.add(blockhain_desc)
.add(storage_desc)
.add(network_desc)
.add(development_desc)
.add(db_editor_desc)
.add(benchmark_desc);
.add(development_desc);
if (command == "db-editor") {
desc.add(db_editor_desc);
} else if (command == "benchmark") {
desc.add(benchmark_desc);
}

if (vm.count("help") > 0) {
std::cout << desc << std::endl;
@@ -1326,7 +1348,7 @@ namespace kagome::application {
subcommand_ = Subcommand::ChainInfo;
});

if (command == Command::Benchmark) {
if (command == "benchmark" && subcommand == "block") {
auto from_opt = find_argument<uint32_t>(vm, "from");
if (!from_opt) {
SL_ERROR(logger_, "Required argument --from is not provided");
@@ -1345,34 +1367,24 @@ namespace kagome::application {
benchmark_config_ = BlockBenchmarkConfig{
.from = *from_opt, .to = *to_opt, .times = *repeat_opt};
}
if (found_num == 0) {
SL_ERROR(logger_, "Found no benchmark options, one must be chosen.");
return false;
}
if (found_num > 1) {
SL_ERROR(logger_,
"Found several benchmark options, only one must be chosen.");

bool has_recovery = false;
find_argument<std::string>(vm, "recovery", [&](const std::string &val) {
has_recovery = true;
recovery_state_ = str_to_recovery_state(val);
if (not recovery_state_) {
SL_ERROR(logger_, "Invalid recovery state specified: '{}'", val);
}
});
if (has_recovery and not recovery_state_.has_value()) {
return false;
}
}

bool has_recovery = false;
find_argument<std::string>(vm, "recovery", [&](const std::string &val) {
has_recovery = true;
recovery_state_ = str_to_recovery_state(val);
if (not recovery_state_) {
SL_ERROR(logger_, "Invalid recovery state specified: '{}'", val);
// if something wrong with config print help message
if (not validate_config()) {
std::cout << desc << std::endl;
return false;
}
});
if (has_recovery and not recovery_state_.has_value()) {
return false;
}

// if something wrong with config print help message
if (not validate_config()) {
std::cout << desc << std::endl;
return false;
return true;
}
return true;
}
} // namespace kagome::application
5 changes: 1 addition & 4 deletions core/application/impl/app_configuration_impl.hpp
Original file line number Diff line number Diff line change
@@ -63,11 +63,8 @@ namespace kagome::application {
AppConfigurationImpl(AppConfigurationImpl &&) = default;
AppConfigurationImpl &operator=(AppConfigurationImpl &&) = default;

enum class Command { Kagome, Benchmark, DbEditor };

[[nodiscard]] bool initializeFromArgs(int argc,
const char **argv,
Command command = Command::Kagome);
const char **argv);

network::Roles roles() const override {
return roles_;
51 changes: 30 additions & 21 deletions core/benchmark/block_execution_benchmark.cpp
Original file line number Diff line number Diff line change
@@ -65,13 +65,19 @@ namespace kagome::benchmark {
BlockExecutionBenchmark::BlockExecutionBenchmark(
std::shared_ptr<runtime::Core> core_api,
std::shared_ptr<const blockchain::BlockTree> block_tree,
std::shared_ptr<runtime::ModuleRepository> module_repo,
std::shared_ptr<const runtime::RuntimeCodeProvider> code_provider,
std::shared_ptr<const storage::trie::TrieStorage> trie_storage)
: logger_{log::createLogger("BlockExecutionBenchmark", "benchmark")},
core_api_{core_api},
block_tree_{block_tree},
module_repo_{module_repo},
code_provider_{code_provider},
trie_storage_{trie_storage} {
BOOST_ASSERT(block_tree_ != nullptr);
BOOST_ASSERT(core_api_ != nullptr);
BOOST_ASSERT(module_repo_ != nullptr);
BOOST_ASSERT(code_provider_ != nullptr);
BOOST_ASSERT(trie_storage_ != nullptr);
}

@@ -192,19 +198,14 @@ namespace kagome::benchmark {
OUTCOME_TRY(batch, storage.getEphemeralBatchAt(state));

OUTCOME_TRY(enc_block_weight, batch->get(BLOCK_WEIGHT_KEY));
auto logger_ = log::createLogger("TEST");
logger_->info("Encoded weight: {}", enc_block_weight.view().toHex());
scale::ScaleDecoderStream stream{enc_block_weight};
ConsumedWeight block_weight;
try {
stream >> block_weight;
} catch (std::exception &e) {
logger_->error("Error decoding encoded block weight: {}", e.what());
return BlockExecutionBenchmark::Error::BLOCK_WEIGHT_DECODE_FAILED;
}
if (stream.hasMore(1)) {
logger_->error(
"Encoded block weight contains more data than were decoded.");
return BlockExecutionBenchmark::Error::BLOCK_WEIGHT_DECODE_FAILED;
}

@@ -251,27 +252,33 @@ namespace kagome::benchmark {
duration_stats.emplace_back(Stats<std::chrono::nanoseconds>{
primitives::BlockInfo{block_hashes[i], blocks[i].header.number}});
}
for (uint16_t i = 0; i < config.times; i++) {
auto duration_stat_it = duration_stats.begin();
for (size_t block_i = 0; block_i < blocks.size(); block_i++) {
auto duration_stat_it = duration_stats.begin();
for (size_t block_i = 0; block_i < blocks.size(); block_i++) {
OUTCOME_TRY(module_repo_->getInstanceAt(
code_provider_,
primitives::BlockInfo{block_hashes[block_i],
blocks[block_i].header.number},
blocks[block_i].header));
for (uint16_t i = 0; i < config.times; i++) {
auto start = clock.now();
OUTCOME_TRY_MSG_VOID(core_api_->execute_block(blocks[block_i], std::nullopt),
"execution of block {}",
block_hashes[i]);
OUTCOME_TRY_MSG_VOID(
core_api_->execute_block(blocks[block_i], std::nullopt),
"execution of block {}",
block_hashes[i]);
auto end = clock.now();
auto duration_ns =
std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
duration_stat_it->add(duration_ns);
SL_INFO(logger_,
"Block #{}, {} ns",
blocks[block_i].header.number,
duration_ns.count());
duration_stat_it++;
SL_VERBOSE(logger_,
"Block #{}, {} ns",
blocks[block_i].header.number,
duration_ns.count());
}
duration_stat_it++;
}
for (auto &stat : duration_stats) {
logger_->info(
"Block #{}, min {:L} ns, avg {:L} ns, median {:L} ns, max {:L} ns",
SL_INFO(logger_,
"Block #{}, min {} ns, avg {} ns, median {} ns, max {} ns",
stat.getBlock().number,
stat.min().count(),
stat.avg().count(),
@@ -280,9 +287,11 @@ namespace kagome::benchmark {
OUTCOME_TRY(
block_weight_ns,
getBlockWeightAsNanoseconds(
*trie_storage_, blocks[stat.getBlock().number - config.start].header.state_root));
logger_->info(
"Block {:L}: consumed {:L} ns out of declared {:L} ns on average. ({} %)",
*trie_storage_,
blocks[stat.getBlock().number - config.start].header.state_root));
SL_INFO(
logger_,
"Block {}: consumed {} ns out of declared {} ns on average. ({} %)",
stat.getBlock().number,
stat.avg().count(),
block_weight_ns.count(),
10 changes: 8 additions & 2 deletions core/benchmark/block_execution_benchmark.hpp
Original file line number Diff line number Diff line change
@@ -8,17 +8,19 @@

#include <memory>

#include "primitives/common.hpp"
#include "log/logger.hpp"
#include "outcome/outcome.hpp"
#include "primitives/common.hpp"

namespace kagome::blockchain {
class BlockTree;
}

namespace kagome::runtime {
class Core;
}
class ModuleRepository;
class RuntimeCodeProvider;
} // namespace kagome::runtime

namespace kagome::storage::trie {
class TrieStorage;
@@ -41,6 +43,8 @@ namespace kagome::benchmark {
BlockExecutionBenchmark(
std::shared_ptr<runtime::Core> core_api,
std::shared_ptr<const blockchain::BlockTree> block_tree,
std::shared_ptr<runtime::ModuleRepository> module_repo,
std::shared_ptr<const runtime::RuntimeCodeProvider> code_provider,
std::shared_ptr<const storage::trie::TrieStorage> trie_storage);

outcome::result<void> run(Config config);
@@ -49,6 +53,8 @@ namespace kagome::benchmark {
log::Logger logger_;
std::shared_ptr<runtime::Core> core_api_;
std::shared_ptr<const blockchain::BlockTree> block_tree_;
std::shared_ptr<runtime::ModuleRepository> module_repo_;
std::shared_ptr<const runtime::RuntimeCodeProvider> code_provider_;
std::shared_ptr<const storage::trie::TrieStorage> trie_storage_;
};

4 changes: 1 addition & 3 deletions core/injector/application_injector.cpp
Original file line number Diff line number Diff line change
@@ -44,7 +44,6 @@
#include "application/app_configuration.hpp"
#include "application/impl/app_state_manager_impl.hpp"
#include "application/impl/chain_spec_impl.hpp"
#include "application/modes/benchmark_mode.hpp"
#include "application/modes/print_chain_info_mode.hpp"
#include "application/modes/recovery_mode.hpp"
#include "authority_discovery/publisher/address_publisher.hpp"
@@ -1380,8 +1379,7 @@ namespace kagome::injector {
}

std::shared_ptr<benchmark::BlockExecutionBenchmark>
KagomeNodeInjector::injectBlockBenchmark();
{
KagomeNodeInjector::injectBlockBenchmark() {
return pimpl_->injector_
.template create<sptr<benchmark::BlockExecutionBenchmark>>();
}
1 change: 1 addition & 0 deletions core/storage/rocksdb/rocksdb_spaces.cpp
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ namespace kagome::storage {
"justification",
"trie_node",
"block_data",
"trie_pruner"
};
assert(names.size() == Space::kTotal);
assert(space < Space::kTotal);
3 changes: 3 additions & 0 deletions core/storage/spaces.hpp
Original file line number Diff line number Diff line change
@@ -21,6 +21,9 @@ namespace kagome::storage {
kJustification,
kTrieNode,

kTriePruner,
kBlockData,

//
kTotal
};
8 changes: 2 additions & 6 deletions core/utils/benchmark_main.cpp
Original file line number Diff line number Diff line change
@@ -12,20 +12,16 @@ namespace kagome {

int benchmark_main(int argc, const char **argv) {
log::Logger config_logger = log::createLogger("Configuration");
if (argc == 0) {
if (argc == 1) {
SL_ERROR(config_logger,
"Usage: kagome benchmark BENCHMARK-TYPE BENCHMARK-OPTIONS\n"
"Available benchmark types are: block");
return -1;
}

const char *benchmark_type = argv[0];
argc--, argv++;

auto config =
std::make_shared<application::AppConfigurationImpl>(config_logger);
if (!config->initializeFromArgs(
argc, argv, application::AppConfiguration::Command::Benchmark)) {
if (!config->initializeFromArgs(argc, argv)) {
SL_ERROR(config_logger, "Failed to initialize kagome!");
return -1;
}
2 changes: 1 addition & 1 deletion node/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ target_link_libraries(kagome
fd_limit
p2p::p2p_identify
p2p::p2p_ping

kagome-benchmark
kagome-db-editor
storage_explorer
)
25 changes: 12 additions & 13 deletions node/main.cpp
Original file line number Diff line number Diff line change
@@ -31,19 +31,6 @@ namespace kagome {
}

int main(int argc, const char **argv) {
if (argc > 1) {
std::string_view name{argv[1]};
if (name == "storage-explorer") {
return storage_explorer_main(argc - 1, argv + 1);
}
if (name == "db-editor") {
return db_editor_main(argc - 1, argv + 1);
}
if (name == "benchmark") {
return kagome::benchmark_main(argc - 1, argv + 1);
}
}

#if defined(BACKWARD_HAS_BACKTRACE)
backward::SignalHandling sh;
#endif
@@ -64,6 +51,18 @@ int main(int argc, const char **argv) {

kagome::log::setLoggingSystem(logging_system);
}
if (argc > 1) {
std::string_view name{argv[1]};
if (name == "storage-explorer") {
return storage_explorer_main(argc - 1, argv + 1);
}
if (name == "db-editor") {
return db_editor_main(argc - 1, argv + 1);
}
if (name == "benchmark") {
return kagome::benchmark_main(argc - 1, argv + 1);
}
}

auto logger = kagome::log::createLogger("AppConfiguration",
kagome::log::defaultGroupName);