From 8329a589942b69547a9a132b5d091976391b1a8b Mon Sep 17 00:00:00 2001 From: EmelyanenkoK Date: Sat, 10 Sep 2022 12:57:13 +0300 Subject: [PATCH] Add GetPerfTimerStats (#451) * Add getperfwarningtimeraverage query for validator-engine-console * Fix for getperfwarningtimeraverage query * getperftimerstats * Add history max size: 1 hour * PerfWarningTimer: move callback instead of copy * PerfWarningTimer: fix move constructor bug * PerfWarningTimer: fix bug: lifetime of the callback was greater than lifetime of the local variable 'manager' captured by reference * Fix validate-query.cpp: 'manager' used after it was moved * PerfWarningTimer: remove logs * getperftimerstats: write to json file * getperftimerstatsjson Co-authored-by: legaii Co-authored-by: Ivan Siomash <106972486+legaii@users.noreply.github.com> --- tdutils/td/utils/Timer.cpp | 11 ++-- tdutils/td/utils/Timer.h | 5 +- tl/generate/scheme/ton_api.tl | 6 +++ tl/generate/scheme/ton_api.tlo | Bin 68244 -> 69024 bytes .../validator-engine-console-query.cpp | 50 +++++++++++++++++ .../validator-engine-console-query.h | 21 ++++++++ .../validator-engine-console.cpp | 1 + validator-engine/validator-engine.cpp | 51 ++++++++++++++++++ validator-engine/validator-engine.hpp | 2 + validator/apply-block.hpp | 7 ++- validator/downloaders/wait-block-data.hpp | 7 ++- validator/downloaders/wait-block-state.hpp | 7 ++- validator/impl/accept-block.cpp | 15 ++++-- validator/impl/accept-block.hpp | 2 +- validator/impl/check-proof.hpp | 17 ++++-- validator/impl/collator-impl.h | 2 +- validator/impl/collator.cpp | 5 +- validator/impl/validate-query.cpp | 7 ++- validator/impl/validate-query.hpp | 2 +- validator/manager-disk.hpp | 7 +++ validator/manager-hardfork.hpp | 7 +++ validator/manager.cpp | 18 +++++++ validator/manager.hpp | 5 ++ validator/validate-broadcast.hpp | 7 ++- validator/validator.h | 9 ++++ 25 files changed, 244 insertions(+), 27 deletions(-) diff --git a/tdutils/td/utils/Timer.cpp b/tdutils/td/utils/Timer.cpp index acd77f63..f33a30dc 100644 --- a/tdutils/td/utils/Timer.cpp +++ b/tdutils/td/utils/Timer.cpp @@ -60,12 +60,12 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Timer &timer) { return string_builder << format::as_time(timer.elapsed()); } -PerfWarningTimer::PerfWarningTimer(string name, double max_duration) - : name_(std::move(name)), start_at_(Time::now()), max_duration_(max_duration) { +PerfWarningTimer::PerfWarningTimer(string name, double max_duration, std::function&& callback) + : name_(std::move(name)), start_at_(Time::now()), max_duration_(max_duration), callback_(std::move(callback)) { } PerfWarningTimer::PerfWarningTimer(PerfWarningTimer &&other) - : name_(std::move(other.name_)), start_at_(other.start_at_), max_duration_(other.max_duration_) { + : name_(std::move(other.name_)), start_at_(other.start_at_), max_duration_(other.max_duration_), callback_(std::move(other.callback_)) { other.start_at_ = 0; } @@ -78,8 +78,9 @@ void PerfWarningTimer::reset() { return; } double duration = Time::now() - start_at_; - LOG_IF(WARNING, duration > max_duration_) - << "SLOW: " << tag("name", name_) << tag("duration", format::as_time(duration)); + //LOG_IF(WARNING, duration > max_duration_) + //<< "SLOW: " << tag("name", name_) << tag("duration", format::as_time(duration)); + callback_(duration); start_at_ = 0; } diff --git a/tdutils/td/utils/Timer.h b/tdutils/td/utils/Timer.h index 7dec45cf..64f3e934 100644 --- a/tdutils/td/utils/Timer.h +++ b/tdutils/td/utils/Timer.h @@ -20,6 +20,8 @@ #include "td/utils/StringBuilder.h" +#include + namespace td { class Timer { @@ -44,7 +46,7 @@ class Timer { class PerfWarningTimer { public: - explicit PerfWarningTimer(string name, double max_duration = 0.1); + explicit PerfWarningTimer(string name, double max_duration = 0.1, std::function&& callback = [] (double) {}); PerfWarningTimer(const PerfWarningTimer &) = delete; PerfWarningTimer &operator=(const PerfWarningTimer &) = delete; PerfWarningTimer(PerfWarningTimer &&other); @@ -56,6 +58,7 @@ class PerfWarningTimer { string name_; double start_at_{0}; double max_duration_{0}; + std::function callback_; }; } // namespace td diff --git a/tl/generate/scheme/ton_api.tl b/tl/generate/scheme/ton_api.tl index 7dc6d8ca..78a682da 100644 --- a/tl/generate/scheme/ton_api.tl +++ b/tl/generate/scheme/ton_api.tl @@ -630,6 +630,10 @@ engine.validator.overlayStatsNode adnl_id:int256 ip_addr:string bdcst_errors:int engine.validator.overlayStats overlay_id:int256 overlay_id_full:PublicKey adnl_id:int256 scope:string nodes:(vector engine.validator.overlayStatsNode) stats:(vector engine.validator.oneStat) = engine.validator.OverlayStats; engine.validator.overlaysStats overlays:(vector engine.validator.overlayStats) = engine.validator.OverlaysStats; +engine.validator.onePerfTimerStat time:int min:double avg:double max:double = engine.validator.OnePerfTimerStat; +engine.validator.perfTimerStatsByName name:string stats:(vector engine.validator.OnePerfTimerStat) = engine.validator.PerfTimerStatsByName; +engine.validator.perfTimerStats stats:(vector engine.validator.PerfTimerStatsByName) = engine.validator.PerfTimerStats; + ---functions--- @@ -680,6 +684,8 @@ engine.validator.importCertificate overlay_id:int256 local_id:adnl.id.short sign engine.validator.signShardOverlayCertificate workchain:int shard:long signed_key:engine.validator.KeyHash expire_at:int max_size:int = overlay.Certificate; engine.validator.importShardOverlayCertificate workchain:int shard:long signed_key:engine.validator.KeyHash cert:overlay.Certificate = engine.validator.Success; +engine.validator.getPerfTimerStats name:string = engine.validator.PerfTimerStats; + ---types--- storage.pong = storage.Pong; diff --git a/tl/generate/scheme/ton_api.tlo b/tl/generate/scheme/ton_api.tlo index c49612788983ca6776a9977c3b0bbb6bc2701e05..8abffd746bad60da62e384b2460103ef2cac77a4 100644 GIT binary patch delta 481 zcmbO-m1V(f7T!m*^{p77;LJwebWyd8#mW;EQ}fa@^HTN75_2+B5=-)n^!)Qu15%69 zLNaqxi-JoMOD6kqNKY;meXk-NdLdpOLph4t;>jC0BsI?NYEmVj&Z*KbF?aGoZt2Y_ zVh;R_PMepieotZrJ81I44iO0yQyCaQ5;u{FgBFpHHrH#2Y2NeLF_#IkfS zots!O>7)oxku#ePhi%(IkcQ0@IyhJ~u)Ded*@wj-HIvu$8iYInIvo~9Frz?{FtMw0 zTrnUunBGG*5bV8F1_qGY$tx!4PTtw8ECF&8%pjQIAO)LydV2gA<2Fm)wiji6|HJ8( j(qzF8XhBfS0CEN>2pA`?ouEAV!vqc%kjQ4A4<1qgS`4wL delta 62 zcmZ25n`O#W7T!m*^{p77;N(W$bkWIML_cg+5qIEcwBMYn_C0B{OxGXg%@+L)evGl3 Ociy!Z-JJ5-MhXCk_!hnZ diff --git a/validator-engine-console/validator-engine-console-query.cpp b/validator-engine-console/validator-engine-console-query.cpp index 35d2e65d..261c0616 100644 --- a/validator-engine-console/validator-engine-console-query.cpp +++ b/validator-engine-console/validator-engine-console-query.cpp @@ -1005,3 +1005,53 @@ td::Status ImportShardOverlayCertificateQuery::receive(td::BufferSlice data) { td::TerminalIO::out() << "successfully sent certificate to overlay manager\n"; return td::Status::OK(); } + +td::Status GetPerfTimerStatsJsonQuery::run() { + TRY_RESULT_ASSIGN(file_name_, tokenizer_.get_token()); + TRY_STATUS(tokenizer_.check_endl()); + return td::Status::OK(); +} + +td::Status GetPerfTimerStatsJsonQuery::send() { + auto b = ton::create_serialize_tl_object(""); + td::actor::send_closure(console_, &ValidatorEngineConsole::envelope_send_query, std::move(b), create_promise()); + return td::Status::OK(); +} + +td::Status GetPerfTimerStatsJsonQuery::receive(td::BufferSlice data) { + TRY_RESULT_PREFIX(f, ton::fetch_tl_object(data.as_slice(), true), + "received incorrect answer: "); + std::ofstream sb(file_name_); + + sb << "{"; + bool gtail = false; + for (const auto &v : f->stats_) { + if (gtail) { + sb << ","; + } else { + gtail = true; + } + + sb << "\n '" << v->name_ << "': {"; + bool tail = false; + for (const auto &stat : v->stats_) { + if (tail) { + sb << ","; + } else { + tail = true; + } + + sb << "\n " << stat->time_ << ": ["; + sb << "\n " << stat->min_ << ","; + sb << "\n " << stat->avg_ << ","; + sb << "\n " << stat->max_; + sb << "\n ]"; + } + sb << "\n }"; + } + sb << "\n}\n"; + sb << std::flush; + + td::TerminalIO::output(std::string("wrote stats to " + file_name_ + "\n")); + return td::Status::OK(); +} diff --git a/validator-engine-console/validator-engine-console-query.h b/validator-engine-console/validator-engine-console-query.h index 15b77314..ab2141dd 100644 --- a/validator-engine-console/validator-engine-console-query.h +++ b/validator-engine-console/validator-engine-console-query.h @@ -1075,3 +1075,24 @@ class ImportShardOverlayCertificateQuery : public Query { std::string in_file_; }; +class GetPerfTimerStatsJsonQuery : public Query { + public: + GetPerfTimerStatsJsonQuery(td::actor::ActorId console, Tokenizer tokenizer) + : Query(console, std::move(tokenizer)) { + } + td::Status run() override; + td::Status send() override; + td::Status receive(td::BufferSlice data) override; + static std::string get_name() { + return "getperftimerstatsjson"; + } + static std::string get_help() { + return "getperftimerstatsjson \tgets min, average and max event processing time for last 60, 300 and 3600 seconds and writes to json file"; + } + std::string name() const override { + return get_name(); + } + + private: + std::string file_name_; +}; diff --git a/validator-engine-console/validator-engine-console.cpp b/validator-engine-console/validator-engine-console.cpp index 1b3f3376..5ce8526b 100644 --- a/validator-engine-console/validator-engine-console.cpp +++ b/validator-engine-console/validator-engine-console.cpp @@ -140,6 +140,7 @@ void ValidatorEngineConsole::run() { add_query_runner(std::make_unique>()); add_query_runner(std::make_unique>()); add_query_runner(std::make_unique>()); + add_query_runner(std::make_unique>()); } bool ValidatorEngineConsole::envelope_send_query(td::BufferSlice query, td::Promise promise) { diff --git a/validator-engine/validator-engine.cpp b/validator-engine/validator-engine.cpp index f380b003..9679ee01 100644 --- a/validator-engine/validator-engine.cpp +++ b/validator-engine/validator-engine.cpp @@ -66,9 +66,11 @@ #include #include #include +#include #include #include "git.h" + Config::Config() { out_port = 3278; full_node = ton::PublicKeyHash::zero(); @@ -3280,6 +3282,55 @@ void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getOverla }); } +void ValidatorEngine::run_control_query(ton::ton_api::engine_validator_getPerfTimerStats &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { + if (!(perm & ValidatorEnginePermissions::vep_default)) { + promise.set_value(create_control_query_error(td::Status::Error(ton::ErrorCode::error, "not authorized"))); + return; + } + + if (validator_manager_.empty()) { + promise.set_value( + create_control_query_error(td::Status::Error(ton::ErrorCode::notready, "validator manager not started"))); + return; + } + + auto P = td::PromiseCreator::lambda( + [promise = std::move(promise), query = std::move(query)](td::Result> R) mutable { + const std::vector times{60, 300, 3600}; + double now = td::Time::now(); + if (R.is_error()) { + promise.set_value(create_control_query_error(R.move_as_error())); + } else { + auto r = R.move_as_ok(); + std::vector> by_name; + for (const auto &stats : r) { + if (stats.name == query.name_ || query.name_.empty()) { + std::vector> by_time; + for (const auto &t : times) { + double min = std::numeric_limits::lowest(); + double max = std::numeric_limits::max(); + double sum = 0; + int cnt = 0; + for (const auto &[time, duration] : stats.stats) { + if (now - time <= static_cast(t)) { + min = td::min(min, duration); + max = td::max(max, duration); + sum += duration; + ++cnt; + } + } + by_time.push_back(ton::create_tl_object(t, min, sum / static_cast(cnt), max)); + } + by_name.push_back(ton::create_tl_object(stats.name, std::move(by_time))); + } + } + promise.set_value(ton::create_serialize_tl_object(std::move(by_name))); + } + }); + td::actor::send_closure(validator_manager_, &ton::validator::ValidatorManagerInterface::prepare_perf_timer_stats, std::move(P)); +} + void ValidatorEngine::process_control_query(td::uint16 port, ton::adnl::AdnlNodeIdShort src, ton::adnl::AdnlNodeIdShort dst, td::BufferSlice data, td::Promise promise) { diff --git a/validator-engine/validator-engine.hpp b/validator-engine/validator-engine.hpp index 3f4fea2c..7284a5be 100644 --- a/validator-engine/validator-engine.hpp +++ b/validator-engine/validator-engine.hpp @@ -407,6 +407,8 @@ class ValidatorEngine : public td::actor::Actor { ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); void run_control_query(ton::ton_api::engine_validator_getOverlaysStats &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); + void run_control_query(ton::ton_api::engine_validator_getPerfTimerStats &query, td::BufferSlice data, + ton::PublicKeyHash src, td::uint32 perm, td::Promise promise); template void run_control_query(T &query, td::BufferSlice data, ton::PublicKeyHash src, td::uint32 perm, td::Promise promise) { diff --git a/validator/apply-block.hpp b/validator/apply-block.hpp index 67ee3911..95deb025 100644 --- a/validator/apply-block.hpp +++ b/validator/apply-block.hpp @@ -46,7 +46,10 @@ class ApplyBlock : public td::actor::Actor { , masterchain_block_id_(masterchain_block_id) , manager_(manager) , timeout_(timeout) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("applyblock", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "applyblock", duration); + }) { } static constexpr td::uint32 apply_block_priority() { @@ -78,7 +81,7 @@ class ApplyBlock : public td::actor::Actor { BlockHandle handle_; td::Ref state_; - td::PerfWarningTimer perf_timer_{"applyblock", 0.1}; + td::PerfWarningTimer perf_timer_; }; } // namespace validator diff --git a/validator/downloaders/wait-block-data.hpp b/validator/downloaders/wait-block-data.hpp index 73097d30..9a03b1cb 100644 --- a/validator/downloaders/wait-block-data.hpp +++ b/validator/downloaders/wait-block-data.hpp @@ -35,7 +35,10 @@ class WaitBlockData : public td::actor::Actor { , priority_(priority) , manager_(manager) , timeout_(timeout) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("waitdata", 1.0, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "waitdata", duration); + }) { } void update_timeout(td::Timestamp timeout, td::uint32 priority) { @@ -74,7 +77,7 @@ class WaitBlockData : public td::actor::Actor { bool is_hardfork_ = false; td::Timestamp try_read_static_file_ = td::Timestamp::now(); - //td::PerfWarningTimer perf_timer_{"waitdata", 1.0}; + td::PerfWarningTimer perf_timer_; }; } // namespace validator diff --git a/validator/downloaders/wait-block-state.hpp b/validator/downloaders/wait-block-state.hpp index a93f2971..7cdc0699 100644 --- a/validator/downloaders/wait-block-state.hpp +++ b/validator/downloaders/wait-block-state.hpp @@ -32,7 +32,10 @@ class WaitBlockState : public td::actor::Actor { , priority_(priority) , manager_(manager) , timeout_(timeout) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("waitstate", 1.0, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "waitstate", duration); + }) { } void abort_query(td::Status reason); @@ -80,7 +83,7 @@ class WaitBlockState : public td::actor::Actor { bool reading_from_db_ = false; td::Timestamp next_static_file_attempt_; - //td::PerfWarningTimer perf_timer_{"waitstate", 1.0}; + td::PerfWarningTimer perf_timer_; }; } // namespace validator diff --git a/validator/impl/accept-block.cpp b/validator/impl/accept-block.cpp index a5c4d9a1..ff953b66 100644 --- a/validator/impl/accept-block.cpp +++ b/validator/impl/accept-block.cpp @@ -53,7 +53,10 @@ AcceptBlockQuery::AcceptBlockQuery(BlockIdExt id, td::Ref data, std:: , is_fork_(false) , send_broadcast_(send_broadcast) , manager_(manager) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("acceptblock", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "acceptblock", duration); + }) { state_keep_old_hash_.clear(); state_old_hash_.clear(); state_hash_.clear(); @@ -71,7 +74,10 @@ AcceptBlockQuery::AcceptBlockQuery(AcceptBlockQuery::IsFake fake, BlockIdExt id, , is_fork_(false) , send_broadcast_(false) , manager_(manager) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("acceptblock", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "acceptblock", duration); + }) { state_keep_old_hash_.clear(); state_old_hash_.clear(); state_hash_.clear(); @@ -86,7 +92,10 @@ AcceptBlockQuery::AcceptBlockQuery(ForceFork ffork, BlockIdExt id, td::Ref top_block_descr_; - td::PerfWarningTimer perf_timer_{"acceptblock", 0.1}; + td::PerfWarningTimer perf_timer_; bool fatal_error(std::string msg, int code = -666); static bool check_send_error(td::actor::ActorId SelfId, td::Status error); diff --git a/validator/impl/check-proof.hpp b/validator/impl/check-proof.hpp index 4461b5e1..5c9a29b5 100644 --- a/validator/impl/check-proof.hpp +++ b/validator/impl/check-proof.hpp @@ -47,7 +47,10 @@ class CheckProof : public td::actor::Actor { , manager_(manager) , timeout_(timeout) , promise_(std::move(promise)) - , skip_check_signatures_(skip_check_signatures) { + , skip_check_signatures_(skip_check_signatures) + , perf_timer_("checkproof", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "checkproof", duration); + }) { } CheckProof(BlockIdExt id, td::Ref proof, td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise, bool skip_check_signatures, td::Ref known_state) @@ -58,7 +61,10 @@ class CheckProof : public td::actor::Actor { , timeout_(timeout) , promise_(std::move(promise)) , state_(std::move(known_state)) - , skip_check_signatures_(skip_check_signatures) { + , skip_check_signatures_(skip_check_signatures) + , perf_timer_("checkproof", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "checkproof", duration); + }) { } CheckProof(BlockIdExt id, td::Ref proof_link, td::actor::ActorId manager, td::Timestamp timeout, td::Promise promise) @@ -67,7 +73,10 @@ class CheckProof : public td::actor::Actor { , proof_(std::move(proof_link)) , manager_(manager) , timeout_(timeout) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("checkproof", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "checkproof", duration); + }) { } private: @@ -114,7 +123,7 @@ class CheckProof : public td::actor::Actor { bool skip_check_signatures_{false}; bool sig_ok_{false}; - td::PerfWarningTimer perf_timer_{"checkproof", 0.1}; + td::PerfWarningTimer perf_timer_; static bool check_send_error(td::actor::ActorId SelfId, td::Status error); template diff --git a/validator/impl/collator-impl.h b/validator/impl/collator-impl.h index 2dced749..1c9faa58 100644 --- a/validator/impl/collator-impl.h +++ b/validator/impl/collator-impl.h @@ -208,7 +208,7 @@ class Collator final : public td::actor::Actor { std::vector> collated_roots_; std::unique_ptr block_candidate; - td::PerfWarningTimer perf_timer_{"collate", 0.1}; + td::PerfWarningTimer perf_timer_; // block::Account* lookup_account(td::ConstBitPtr addr) const; std::unique_ptr make_account_from(td::ConstBitPtr addr, Ref account, diff --git a/validator/impl/collator.cpp b/validator/impl/collator.cpp index 6aedcc21..84d75e88 100644 --- a/validator/impl/collator.cpp +++ b/validator/impl/collator.cpp @@ -67,7 +67,10 @@ Collator::Collator(ShardIdFull shard, bool is_hardfork, UnixTime min_ts, BlockId , validator_set_(std::move(validator_set)) , manager(manager) , timeout(timeout) - , main_promise(std::move(promise)) { + , main_promise(std::move(promise)) + , perf_timer_("collate", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "collate", duration); + }) { } void Collator::start_up() { diff --git a/validator/impl/validate-query.cpp b/validator/impl/validate-query.cpp index 97a4bab9..61a98bb9 100644 --- a/validator/impl/validate-query.cpp +++ b/validator/impl/validate-query.cpp @@ -59,12 +59,15 @@ ValidateQuery::ValidateQuery(ShardIdFull shard, UnixTime min_ts, BlockIdExt min_ , prev_blocks(std::move(prev)) , block_candidate(std::move(candidate)) , validator_set_(std::move(validator_set)) - , manager(std::move(manager)) + , manager(manager) , timeout(timeout) , main_promise(std::move(promise)) , is_fake_(is_fake) , shard_pfx_(shard_.shard) - , shard_pfx_len_(ton::shard_prefix_length(shard_)) { + , shard_pfx_len_(ton::shard_prefix_length(shard_)) + , perf_timer_("validateblock", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "validateblock", duration); + }) { proc_hash_.zero(); } diff --git a/validator/impl/validate-query.hpp b/validator/impl/validate-query.hpp index 2aef04af..4ddbc445 100644 --- a/validator/impl/validate-query.hpp +++ b/validator/impl/validate-query.hpp @@ -228,7 +228,7 @@ class ValidateQuery : public td::actor::Actor { std::vector> lib_publishers_, lib_publishers2_; - td::PerfWarningTimer perf_timer_{"validateblock", 0.1}; + td::PerfWarningTimer perf_timer_; static constexpr td::uint32 priority() { return 2; diff --git a/validator/manager-disk.hpp b/validator/manager-disk.hpp index b56f8b3e..d5b35d03 100644 --- a/validator/manager-disk.hpp +++ b/validator/manager-disk.hpp @@ -358,6 +358,13 @@ class ValidatorManagerImpl : public ValidatorManager { UNREACHABLE(); } + void prepare_perf_timer_stats(td::Promise> promise) override { + UNREACHABLE(); + } + + void add_perf_timer_stat(std::string name, double duration) override { + } + void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise promise) override { UNREACHABLE(); } diff --git a/validator/manager-hardfork.hpp b/validator/manager-hardfork.hpp index 11470cfd..4fb81de6 100644 --- a/validator/manager-hardfork.hpp +++ b/validator/manager-hardfork.hpp @@ -417,6 +417,13 @@ class ValidatorManagerImpl : public ValidatorManager { UNREACHABLE(); } + void prepare_perf_timer_stats(td::Promise> promise) override { + UNREACHABLE(); + } + + void add_perf_timer_stat(std::string name, double duration) override { + } + void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise promise) override { UNREACHABLE(); } diff --git a/validator/manager.cpp b/validator/manager.cpp index d6a9b4dd..b830bc84 100644 --- a/validator/manager.cpp +++ b/validator/manager.cpp @@ -2495,6 +2495,24 @@ void ValidatorManagerImpl::prepare_stats(td::Promise> promise) { + promise.set_value(std::vector(perf_timer_stats)); +} + +void ValidatorManagerImpl::add_perf_timer_stat(std::string name, double duration) { + for (auto &s : perf_timer_stats) { + if (s.name == name) { + double now = td::Time::now(); + while (!s.stats.empty() && s.stats.front().first < now - 3600.0) { + s.stats.pop_front(); + } + s.stats.push_back({td::Time::now(), duration}); + return; + } + } + perf_timer_stats.push_back({name, {{td::Time::now(), duration}}}); +} + void ValidatorManagerImpl::truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise promise) { td::actor::send_closure(db_, &Db::truncate, seqno, std::move(handle), std::move(promise)); } diff --git a/validator/manager.hpp b/validator/manager.hpp index d7f2c8a3..761fbad7 100644 --- a/validator/manager.hpp +++ b/validator/manager.hpp @@ -255,6 +255,8 @@ class ValidatorManagerImpl : public ValidatorManager { std::map, std::vector>>> pending_masterchain_states_; + std::vector perf_timer_stats; + void new_masterchain_block(); void update_shards(); void update_shard_blocks(); @@ -526,6 +528,9 @@ class ValidatorManagerImpl : public ValidatorManager { void prepare_stats(td::Promise>> promise) override; + void prepare_perf_timer_stats(td::Promise> promise) override; + void add_perf_timer_stat(std::string name, double duration) override; + void truncate(BlockSeqno seqno, ConstBlockHandle handle, td::Promise promise) override; void wait_shard_client_state(BlockSeqno seqno, td::Timestamp timeout, td::Promise promise) override; diff --git a/validator/validate-broadcast.hpp b/validator/validate-broadcast.hpp index 8a6fb149..74496fa3 100644 --- a/validator/validate-broadcast.hpp +++ b/validator/validate-broadcast.hpp @@ -44,7 +44,7 @@ class ValidateBroadcast : public td::actor::Actor { td::Ref proof_link_; BlockHandle handle_; - td::PerfWarningTimer perf_timer_{"validatebroadcast", 0.1}; + td::PerfWarningTimer perf_timer_; bool exact_key_block_handle_; td::Ref key_proof_link_; @@ -60,7 +60,10 @@ class ValidateBroadcast : public td::actor::Actor { , last_known_masterchain_block_handle_(std::move(last_known_masterchain_block_handle)) , manager_(manager) , timeout_(timeout) - , promise_(std::move(promise)) { + , promise_(std::move(promise)) + , perf_timer_("validatebroadcast", 0.1, [manager](double duration) { + send_closure(manager, &ValidatorManager::add_perf_timer_stat, "validatebroadcast", duration); + }) { } void start_up() override; diff --git a/validator/validator.h b/validator/validator.h index fce119a4..49d80286 100644 --- a/validator/validator.h +++ b/validator/validator.h @@ -19,6 +19,7 @@ #pragma once #include +#include #include "td/actor/actor.h" @@ -44,6 +45,11 @@ class DownloadToken { virtual ~DownloadToken() = default; }; +struct PerfTimerStats { + std::string name; + std::deque> stats; // +}; + struct ValidatorManagerOptions : public td::CntObject { public: enum class ShardCheckMode { m_monitor, m_validate }; @@ -214,6 +220,9 @@ class ValidatorManagerInterface : public td::actor::Actor { virtual void run_ext_query(td::BufferSlice data, td::Promise promise) = 0; virtual void prepare_stats(td::Promise>> promise) = 0; + + virtual void prepare_perf_timer_stats(td::Promise> promise) = 0; + virtual void add_perf_timer_stat(std::string name, double duration) = 0; }; } // namespace validator