diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp')
-rw-r--r-- | protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp | 156 |
1 files changed, 105 insertions, 51 deletions
diff --git a/protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp b/protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp index a966d601cf..afe94ca3c1 100644 --- a/protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp +++ b/protocols/Telegram/tdlib/td/benchmark/bench_actor.cpp @@ -1,47 +1,101 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#include "td/utils/benchmark.h" - #include "td/actor/actor.h" +#include "td/actor/ConcurrentScheduler.h" #include "td/actor/PromiseFuture.h" +#include "td/utils/benchmark.h" +#include "td/utils/common.h" +#include "td/utils/crypto.h" #include "td/utils/logging.h" - -#include <algorithm> +#include "td/utils/Promise.h" +#include "td/utils/SliceBuilder.h" #if TD_MSVC #pragma comment(linker, "/STACK:16777216") #endif +struct TestActor final : public td::Actor { + static td::int32 actor_count_; + + void start_up() final { + actor_count_++; + stop(); + } + + void tear_down() final { + if (--actor_count_ == 0) { + td::Scheduler::instance()->finish(); + } + } +}; + +td::int32 TestActor::actor_count_; + +namespace td { +template <> +class ActorTraits<TestActor> { + public: + static constexpr bool need_context = false; + static constexpr bool need_start_up = true; +}; +} // namespace td + +class CreateActorBench final : public td::Benchmark { + td::ConcurrentScheduler scheduler_{0, 0}; + + void start_up() final { + scheduler_.start(); + } + + void tear_down() final { + scheduler_.finish(); + } + + public: + td::string get_description() const final { + return "CreateActor"; + } + + void run(int n) final { + for (int i = 0; i < n; i++) { + scheduler_.create_actor_unsafe<TestActor>(0, "TestActor").release(); + } + while (scheduler_.run_main(10)) { + // empty + } + } +}; + template <int type> -class RingBench : public td::Benchmark { +class RingBench final : public td::Benchmark { public: struct PassActor; private: - int actor_n_; - int thread_n_; - std::vector<td::ActorId<PassActor>> actor_array_; - td::ConcurrentScheduler *scheduler_; + int actor_n_ = -1; + int thread_n_ = -1; + td::vector<td::ActorId<PassActor>> actor_array_; + td::ConcurrentScheduler *scheduler_ = nullptr; public: - std::string get_description() const override { + td::string get_description() const final { static const char *types[] = {"later", "immediate", "raw", "tail", "lambda"}; static_assert(0 <= type && type < 5, ""); return PSTRING() << "Ring (send_" << types[type] << ") (threads_n = " << thread_n_ << ")"; } - struct PassActor : public td::Actor { - int id; + struct PassActor final : public td::Actor { + int id = -1; td::ActorId<PassActor> next_actor; int start_n = 0; void pass(int n) { - // LOG(INFO) << "pass: " << n; + // LOG(INFO) << "Pass: " << n; if (n == 0) { td::Scheduler::instance()->finish(); } else { @@ -56,24 +110,23 @@ class RingBench : public td::Benchmark { send_closure_later(next_actor, &PassActor::pass, n - 1); } else { // TODO: it is three times faster than send_event - // may be send event could be further optimized? - ::td::Scheduler::instance()->hack(static_cast<td::ActorId<Actor>>(next_actor), - td::Event::raw(static_cast<td::uint32>(n - 1))); + // maybe send event could be further optimized? + next_actor.get_actor_unsafe()->raw_event(td::Event::raw(static_cast<td::uint32>(n - 1)).data); } } else if (type == 4) { - send_lambda(next_actor, [=, ptr = next_actor.get_actor_unsafe()] { ptr->pass(n - 1); }); + send_lambda(next_actor, [n, ptr = next_actor.get_actor_unsafe()] { ptr->pass(n - 1); }); } } } - void raw_event(const td::Event::Raw &raw) override { + void raw_event(const td::Event::Raw &raw) final { pass(static_cast<int>(raw.u32)); } - void start_up() override { + void start_up() final { yield(); } - void wakeup() override { + void wakeup() final { if (start_n != 0) { int n = start_n; start_n = 0; @@ -85,11 +138,10 @@ class RingBench : public td::Benchmark { RingBench(int actor_n, int thread_n) : actor_n_(actor_n), thread_n_(thread_n) { } - void start_up() override { - scheduler_ = new td::ConcurrentScheduler(); - scheduler_->init(thread_n_); + void start_up() final { + scheduler_ = new td::ConcurrentScheduler(thread_n_, 0); - actor_array_ = std::vector<td::ActorId<PassActor>>(actor_n_); + actor_array_ = td::vector<td::ActorId<PassActor>>(actor_n_); for (int i = 0; i < actor_n_; i++) { actor_array_[i] = scheduler_->create_actor_unsafe<PassActor>(thread_n_ ? i % thread_n_ : 0, "PassActor").release(); @@ -101,30 +153,30 @@ class RingBench : public td::Benchmark { scheduler_->start(); } - void run(int n) override { + void run(int n) final { // first actor is on main_thread - actor_array_[0].get_actor_unsafe()->start_n = std::max(n, 100); + actor_array_[0].get_actor_unsafe()->start_n = td::max(n, 100); while (scheduler_->run_main(10)) { // empty } } - void tear_down() override { + void tear_down() final { scheduler_->finish(); delete scheduler_; } }; template <int type> -class QueryBench : public td::Benchmark { +class QueryBench final : public td::Benchmark { public: - std::string get_description() const override { + td::string get_description() const final { static const char *types[] = {"callback", "immediate future", "delayed future", "dummy", "lambda", "lambda_future"}; static_assert(0 <= type && type < 6, ""); return PSTRING() << "QueryBench: " << types[type]; } - class ClientActor : public td::Actor { + class ClientActor final : public td::Actor { public: class Callback { public: @@ -136,7 +188,7 @@ class QueryBench : public td::Benchmark { virtual ~Callback() = default; virtual void on_result(int x) = 0; }; - explicit ClientActor(std::unique_ptr<Callback> callback) : callback_(std::move(callback)) { + explicit ClientActor(td::unique_ptr<Callback> callback) : callback_(std::move(callback)) { } void f(int x) { callback_->on_result(x * x); @@ -152,23 +204,23 @@ class QueryBench : public td::Benchmark { } private: - std::unique_ptr<Callback> callback_; + td::unique_ptr<Callback> callback_; }; - class ServerActor : public td::Actor { + class ServerActor final : public td::Actor { public: - class ClientCallback : public ClientActor::Callback { + class ClientCallback final : public ClientActor::Callback { public: explicit ClientCallback(td::ActorId<ServerActor> server) : server_(server) { } - void on_result(int x) override { + void on_result(int x) final { send_closure(server_, &ServerActor::on_result, x); } private: td::ActorId<ServerActor> server_; }; - void start_up() override { + void start_up() final { client_ = td::create_actor<ClientActor>("Client", td::make_unique<ClientCallback>(actor_id(this))).release(); } @@ -177,7 +229,7 @@ class QueryBench : public td::Benchmark { wakeup(); } - void wakeup() override { + void wakeup() final { while (true) { if (n_ < 0) { td::Scheduler::instance()->finish(); @@ -206,10 +258,12 @@ class QueryBench : public td::Benchmark { } else if (type == 4) { int val = 0; send_lambda(client_, [&] { val = n_ * n_; }); + CHECK(val == n_ * n_); } else if (type == 5) { send_closure(client_, &ClientActor::f_promise, - td::PromiseCreator::lambda( - [id = actor_id(this), n = n_](td::Unit) { send_closure(id, &ServerActor::result, n * n); })); + td::PromiseCreator::lambda([actor_id = actor_id(this), n = n_](td::Unit) { + send_closure(actor_id, &ServerActor::result, n * n); + })); return; } } @@ -220,7 +274,7 @@ class QueryBench : public td::Benchmark { wakeup(); } - void raw_event(const td::Event::Raw &event) override { + void raw_event(const td::Event::Raw &event) final { int val = future_.move_as_ok(); CHECK(val == n_ * n_); wakeup(); @@ -232,22 +286,21 @@ class QueryBench : public td::Benchmark { private: td::ActorId<ClientActor> client_; - int n_; + int n_ = 0; td::FutureActor<int> future_; }; - void start_up() override { - scheduler_ = new td::ConcurrentScheduler(); - scheduler_->init(0); + void start_up() final { + scheduler_ = new td::ConcurrentScheduler(0, 0); server_ = scheduler_->create_actor_unsafe<ServerActor>(0, "Server"); scheduler_->start(); } - void run(int n) override { + void run(int n) final { // first actor is on main_thread { - auto guard = scheduler_->get_current_guard(); + auto guard = scheduler_->get_main_guard(); send_closure(server_, &ServerActor::run, n); } while (scheduler_->run_main(10)) { @@ -255,19 +308,21 @@ class QueryBench : public td::Benchmark { } } - void tear_down() override { + void tear_down() final { server_.release(); scheduler_->finish(); delete scheduler_; } private: - td::ConcurrentScheduler *scheduler_; + td::ConcurrentScheduler *scheduler_ = nullptr; td::ActorOwn<ServerActor> server_; }; int main() { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(DEBUG)); + td::init_openssl_threads(); + + bench(CreateActorBench()); bench(RingBench<4>(504, 0)); bench(RingBench<3>(504, 0)); bench(RingBench<0>(504, 0)); @@ -286,5 +341,4 @@ int main() { bench(RingBench<0>(504, 2)); bench(RingBench<1>(504, 2)); bench(RingBench<2>(504, 2)); - return 0; } |