aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorkruall <kruall@ydb.tech>2023-09-11 15:13:49 +0300
committerkruall <kruall@ydb.tech>2023-09-11 15:36:25 +0300
commit37785d3b5bb041cd4a7ca47f37dd374a87cdb97e (patch)
treeaf11a5a1012bf61bfe1743385965a09ee6e9549b /library/cpp
parent7e78e9674adeffb3b3b40c1cc58b022899b41409 (diff)
downloadydb-37785d3b5bb041cd4a7ca47f37dd374a87cdb97e.tar.gz
Improve benchmarks, KIKIMR-19207
Diffstat (limited to 'library/cpp')
-rw-r--r--library/cpp/actors/core/CMakeLists.darwin-x86_64.txt1
-rw-r--r--library/cpp/actors/core/CMakeLists.linux-aarch64.txt1
-rw-r--r--library/cpp/actors/core/CMakeLists.linux-x86_64.txt1
-rw-r--r--library/cpp/actors/core/CMakeLists.windows-x86_64.txt1
-rw-r--r--library/cpp/actors/core/actor_benchmark_helper.h763
-rw-r--r--library/cpp/actors/core/actor_ut.cpp601
-rw-r--r--library/cpp/actors/core/ut_fat/CMakeLists.darwin-x86_64.txt71
-rw-r--r--library/cpp/actors/core/ut_fat/CMakeLists.linux-aarch64.txt74
-rw-r--r--library/cpp/actors/core/ut_fat/CMakeLists.linux-x86_64.txt76
-rw-r--r--library/cpp/actors/core/ut_fat/CMakeLists.txt17
-rw-r--r--library/cpp/actors/core/ut_fat/CMakeLists.windows-x86_64.txt64
-rw-r--r--library/cpp/actors/core/ut_fat/actor_benchmark.cpp46
-rw-r--r--library/cpp/actors/core/ut_fat/ya.make32
-rw-r--r--library/cpp/actors/core/ya.make1
14 files changed, 1297 insertions, 452 deletions
diff --git a/library/cpp/actors/core/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/core/CMakeLists.darwin-x86_64.txt
index c5c16295138..2090b64ba18 100644
--- a/library/cpp/actors/core/CMakeLists.darwin-x86_64.txt
+++ b/library/cpp/actors/core/CMakeLists.darwin-x86_64.txt
@@ -7,6 +7,7 @@
add_subdirectory(ut)
+add_subdirectory(ut_fat)
get_built_tool_path(
TOOL_enum_parser_bin
TOOL_enum_parser_dependency
diff --git a/library/cpp/actors/core/CMakeLists.linux-aarch64.txt b/library/cpp/actors/core/CMakeLists.linux-aarch64.txt
index 23f4e3ba647..24152462c9f 100644
--- a/library/cpp/actors/core/CMakeLists.linux-aarch64.txt
+++ b/library/cpp/actors/core/CMakeLists.linux-aarch64.txt
@@ -7,6 +7,7 @@
add_subdirectory(ut)
+add_subdirectory(ut_fat)
get_built_tool_path(
TOOL_enum_parser_bin
TOOL_enum_parser_dependency
diff --git a/library/cpp/actors/core/CMakeLists.linux-x86_64.txt b/library/cpp/actors/core/CMakeLists.linux-x86_64.txt
index 23f4e3ba647..24152462c9f 100644
--- a/library/cpp/actors/core/CMakeLists.linux-x86_64.txt
+++ b/library/cpp/actors/core/CMakeLists.linux-x86_64.txt
@@ -7,6 +7,7 @@
add_subdirectory(ut)
+add_subdirectory(ut_fat)
get_built_tool_path(
TOOL_enum_parser_bin
TOOL_enum_parser_dependency
diff --git a/library/cpp/actors/core/CMakeLists.windows-x86_64.txt b/library/cpp/actors/core/CMakeLists.windows-x86_64.txt
index c5c16295138..2090b64ba18 100644
--- a/library/cpp/actors/core/CMakeLists.windows-x86_64.txt
+++ b/library/cpp/actors/core/CMakeLists.windows-x86_64.txt
@@ -7,6 +7,7 @@
add_subdirectory(ut)
+add_subdirectory(ut_fat)
get_built_tool_path(
TOOL_enum_parser_bin
TOOL_enum_parser_dependency
diff --git a/library/cpp/actors/core/actor_benchmark_helper.h b/library/cpp/actors/core/actor_benchmark_helper.h
new file mode 100644
index 00000000000..0671271f42a
--- /dev/null
+++ b/library/cpp/actors/core/actor_benchmark_helper.h
@@ -0,0 +1,763 @@
+#include "actor.h"
+#include "events.h"
+#include "actorsystem.h"
+#include "executor_pool_basic.h"
+#include "scheduler_basic.h"
+#include "actor_bootstrapped.h"
+
+#include <library/cpp/actors/testlib/test_runtime.h>
+#include <library/cpp/actors/util/threadparkpad.h>
+#include <library/cpp/testing/unittest/registar.h>
+#include <library/cpp/threading/chunk_queue/queue.h>
+
+#include <util/generic/algorithm.h>
+#include <library/cpp/deprecated/atomic/atomic.h>
+#include <util/system/rwlock.h>
+#include <util/system/hp_timer.h>
+#include <vector>
+
+namespace NActors::NTests {
+
+struct TTestEndDecorator : TDecorator {
+ TThreadParkPad* Pad;
+ TAtomic* ActorsAlive;
+
+ TTestEndDecorator(THolder<IActor>&& actor, TThreadParkPad* pad, TAtomic* actorsAlive)
+ : TDecorator(std::move(actor))
+ , Pad(pad)
+ , ActorsAlive(actorsAlive)
+ {
+ AtomicIncrement(*ActorsAlive);
+ }
+
+ ~TTestEndDecorator() {
+ if (AtomicDecrement(*ActorsAlive) == 0) {
+ Pad->Unpark();
+ }
+ }
+};
+
+
+struct TActorBenchmarkSettings {
+ static constexpr bool DefaultNoRealtime = true;
+ static constexpr ui32 DefaultSpinThreshold = 1'000'000;
+ static constexpr ui32 TotalEventsAmountPerThread = 10'000;
+
+ static constexpr auto MailboxTypes = {
+ TMailboxType::Simple,
+ TMailboxType::Revolving,
+ TMailboxType::HTSwap,
+ TMailboxType::ReadAsFilled,
+ TMailboxType::TinyReadAsFilled
+ };
+};
+
+
+template <typename TSettings_ = TActorBenchmarkSettings>
+struct TActorBenchmark {
+ using TSettings = TSettings_;
+
+ class TDummyActor : public TActor<TDummyActor> {
+ public:
+ TDummyActor() : TActor<TDummyActor>(&TDummyActor::StateFunc) {}
+ STFUNC(StateFunc) {
+ (void)ev;
+ }
+ };
+
+ enum class ERole {
+ Leader,
+ Follower
+ };
+
+ struct TEvOwnedPing : TEvents::TEvPing {
+ TEvOwnedPing(TActorId owner)
+ : TEvPing()
+ , Owner(owner)
+ {}
+
+ TActorId Owner;
+ };
+
+ struct TEventSharedCounters {
+ TEventSharedCounters(ui32 count)
+ : NotStarted(count)
+ , Finished(0)
+ , Counters(count)
+ , StartedCounters(count)
+ , EndedCounters(count)
+ {
+ for (ui32 idx = 0; idx < count; ++idx) {
+ Counters[idx].store(0);
+ StartedCounters[idx].store(0);
+ EndedCounters[idx].store(0);
+ }
+ }
+
+ std::atomic<ui64> NotStarted = 0;
+ std::atomic<ui64> Finished = 0;
+ std::vector<NThreading::TPadded<std::atomic<ui64>>> Counters;
+ std::vector<NThreading::TPadded<std::atomic<ui64>>> StartedCounters;
+ std::vector<NThreading::TPadded<std::atomic<ui64>>> EndedCounters;
+ std::atomic<ui64> StartTimeTs = 0;
+ std::atomic<ui64> EndTimeTs = 0;
+ std::atomic<bool> DoStop = false;
+ };
+
+ struct TSendReceiveActorParams {
+ ui64 OwnEvents = 0;
+ ui64 OtherEvents = 0;
+ bool EndlessSending = false;
+ double *ElapsedTime = nullptr;
+ std::vector<TActorId> Receivers;
+ bool Allocation = false;
+ ESendingType SendingType = ESendingType::Common;
+ ui32 Neighbours = 0;
+ TEventSharedCounters *SharedCounters;
+ ui32 InFlight = 1;
+ };
+
+ class TSendReceiveActor : public TActorBootstrapped<TSendReceiveActor> {
+ public:
+ static constexpr auto ActorActivityType() {
+ return IActorCallback::EActivityType::ACTORLIB_COMMON;
+ }
+
+ TSendReceiveActor(const TSendReceiveActorParams &params, ui32 idx=0)
+ : OwnEventsCounter(params.OwnEvents)
+ , OtherEventsCounter(params.OtherEvents)
+ , ElapsedTime(params.ElapsedTime)
+ , Receivers(params.Receivers)
+ , AllocatesMemory(params.Allocation)
+ , SendingType(params.SendingType)
+ , MailboxNeighboursCount(params.Neighbours)
+ , SharedCounters(params.SharedCounters)
+ , PairIdx(idx)
+ , EndlessSending(params.EndlessSending)
+ , IsLeader(OwnEventsCounter)
+ , InFlight(params.InFlight)
+ {}
+
+ void StoreCounters(std::vector<NThreading::TPadded<std::atomic<ui64>>> &dest) {
+ for (ui32 idx = 0; idx < dest.size(); ++idx) {
+ dest[idx].store(SharedCounters->Counters[idx]);
+ }
+ }
+
+ void Bootstrap(const TActorContext &ctx) {
+ if (SharedCounters && IsLeader) {
+ ui32 count = --SharedCounters->NotStarted;
+ if (!count) {
+ SharedCounters->StartTimeTs = GetCycleCountFast();
+ StoreCounters(SharedCounters->StartedCounters);
+ }
+ }
+ if (Receivers.empty() && OwnEventsCounter) {
+ Receivers.push_back(this->SelfId());
+ }
+ Timer.Reset();
+ this->Become(&TSendReceiveActor::StateFunc);
+ for (ui32 i = 0; i < MailboxNeighboursCount; ++i) {
+ ctx.RegisterWithSameMailbox(new TDummyActor());
+ }
+ for (TActorId receiver : Receivers) {
+ for (ui32 eventIdx = 0; eventIdx < InFlight; ++eventIdx) {
+ TAutoPtr<IEventHandle> ev = new IEventHandle(receiver, this->SelfId(), new TEvOwnedPing(this->SelfId()));
+ SpecialSend(ev, ctx, true);
+ }
+ }
+ }
+
+ void SpecialSend(TAutoPtr<IEventHandle> ev, const TActorContext &ctx, bool own) {
+ EventsCounter++;
+ if (own) {
+ --OwnEventsCounter;
+ }
+ if (SendingType == ESendingType::Lazy) {
+ ctx.Send<ESendingType::Lazy>(ev);
+ } else if (SendingType == ESendingType::Tail) {
+ ctx.Send<ESendingType::Tail>(ev);
+ } else {
+ ctx.Send(ev);
+ }
+ }
+
+ void Stop() {
+ if (SharedCounters && IsLeader) {
+ if (!SharedCounters->NotStarted++) {
+ StoreCounters(SharedCounters->EndedCounters);
+ SharedCounters->EndTimeTs = GetCycleCountFast();
+ }
+ }
+ if (ElapsedTime != nullptr) {
+ if (Receivers.size() && Receivers[0] != this->SelfId()) {
+ *ElapsedTime = Timer.Passed() / EventsCounter;
+ } else {
+ *ElapsedTime = Timer.Passed() * 2 / EventsCounter;
+ }
+ }
+ this->PassAway();
+ }
+
+ bool CheckWorkIsDone() {
+ if (OwnEventsCounter || OtherEventsCounter || EndlessSending) {
+ return false;
+ }
+ Stop();
+ return true;
+ }
+
+ STFUNC(StateFunc) {
+ ++EventsCounter;
+ ui32 counter = ++ReceiveTurn;
+ if (SharedCounters) {
+ if (counter % 128 == 0) {
+ if (IsLeader) {
+ SharedCounters->Counters[PairIdx].store(EventsCounter);
+ }
+ if (SharedCounters->DoStop) {
+ Stop();
+ return;
+ }
+ }
+ }
+ bool own = ev->Get<TEvOwnedPing>()->Owner == this->SelfId();
+ if (!own) {
+ --OtherEventsCounter;
+ }
+ if (CheckWorkIsDone())
+ return;
+
+ auto ctx(this->ActorContext());
+ if (AllocatesMemory) {
+ SpecialSend(new IEventHandle(ev->Sender, this->SelfId(), new TEvOwnedPing(ev->Get<TEvOwnedPing>()->Owner)), ctx, own);
+ } else {
+ std::swap(*const_cast<TActorId*>(&ev->Sender), *const_cast<TActorId*>(&ev->Recipient));
+ ev->DropRewrite();
+ SpecialSend(ev, ctx, own);
+ }
+
+ CheckWorkIsDone();
+ }
+
+ private:
+ THPTimer Timer;
+ ui64 OwnEventsCounter;
+ ui64 OtherEventsCounter;
+ double* ElapsedTime;
+ std::vector<TActorId> Receivers;
+ bool AllocatesMemory;
+ ESendingType SendingType;
+ ui32 MailboxNeighboursCount;
+ ui32 EventsCounter = 0;
+ TEventSharedCounters *SharedCounters;
+ ui32 PairIdx = 0;
+ bool EndlessSending = false;
+ bool IsLeader = false;
+ ui32 InFlight = 1;
+ ui32 ReceiveTurn = 0;
+ };
+
+ static void AddBasicPool(THolder<TActorSystemSetup>& setup, ui32 threads, bool activateEveryEvent, i16 sharedExecutorsCount) {
+ TBasicExecutorPoolConfig basic;
+ basic.PoolId = setup->GetExecutorsCount();
+ basic.PoolName = TStringBuilder() << "b" << basic.PoolId;
+ basic.Threads = threads;
+ basic.SpinThreshold = TSettings::DefaultSpinThreshold;
+ basic.TimePerMailbox = TDuration::Hours(1);
+ basic.SharedExecutorsCount = sharedExecutorsCount;
+ basic.SoftProcessingDurationTs = Us2Ts(100);
+ if (activateEveryEvent) {
+ basic.EventsPerMailbox = 1;
+ }
+ setup->CpuManager.Basic.emplace_back(std::move(basic));
+ }
+
+ static void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency, bool activateEveryEvent) {
+ TUnitedExecutorPoolConfig united;
+ united.PoolId = setup->GetExecutorsCount();
+ united.PoolName = TStringBuilder() << "u" << united.PoolId;
+ united.Concurrency = concurrency;
+ united.TimePerMailbox = TDuration::Hours(1);
+ if (activateEveryEvent) {
+ united.EventsPerMailbox = 1;
+ } else {
+ united.EventsPerMailbox = ::Max<ui32>();
+ }
+ setup->CpuManager.United.emplace_back(std::move(united));
+ }
+
+ static THolder<TActorSystemSetup> GetActorSystemSetup(ui32 unitedCpuCount, bool preemption) {
+ auto setup = MakeHolder<NActors::TActorSystemSetup>();
+ setup->NodeId = 1;
+ setup->CpuManager.UnitedWorkers.CpuCount = unitedCpuCount;
+ setup->CpuManager.UnitedWorkers.SpinThresholdUs = TSettings::DefaultSpinThreshold;
+ setup->CpuManager.UnitedWorkers.NoRealtime = TSettings::DefaultNoRealtime;
+ if (preemption) {
+ setup->CpuManager.UnitedWorkers.PoolLimitUs = 500;
+ setup->CpuManager.UnitedWorkers.EventLimitUs = 100;
+ setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 100;
+ } else {
+ setup->CpuManager.UnitedWorkers.PoolLimitUs = 100'000'000'000;
+ setup->CpuManager.UnitedWorkers.EventLimitUs = 10'000'000'000;
+ setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 10'000'000'000;
+ }
+ setup->Scheduler = new TBasicSchedulerThread(NActors::TSchedulerConfig(512, 0));
+ return setup;
+ }
+
+ enum class EPoolType {
+ Basic,
+ United
+ };
+
+ static THolder<TActorSystemSetup> InitActorSystemSetup(EPoolType poolType, ui32 poolsCount, ui32 threads, bool activateEveryEvent, bool preemption) {
+ if (poolType == EPoolType::Basic) {
+ THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
+ for (ui32 i = 0; i < poolsCount; ++i) {
+ AddBasicPool(setup, threads, activateEveryEvent, 0);
+ }
+ return setup;
+ } else if (poolType == EPoolType::United) {
+ THolder<TActorSystemSetup> setup = GetActorSystemSetup(poolsCount * threads, preemption);
+ for (ui32 i = 0; i < poolsCount; ++i) {
+ AddUnitedPool(setup, threads, activateEveryEvent);
+ }
+ return setup;
+ }
+ Y_FAIL();
+ }
+
+ static double BenchSendReceive(bool allocation, NActors::TMailboxType::EType mType, EPoolType poolType, ESendingType sendingType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ TThreadParkPad pad;
+ TAtomic actorsAlive = 0;
+ double elapsedTime = 0;
+ THolder<IActor> endActor{new TTestEndDecorator(
+ THolder(new TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OwnEvents=TSettings::TotalEventsAmountPerThread,
+ .OtherEvents=0,
+ .ElapsedTime=&elapsedTime,
+ .Allocation=allocation,
+ .SendingType=sendingType,
+ }
+ )),
+ &pad,
+ &actorsAlive
+ )};
+
+ actorSystem.Register(endActor.Release(), mType);
+
+ pad.Park();
+ actorSystem.Stop();
+
+ return 1e9 * elapsedTime;
+ }
+
+ static double BenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType, ESendingType sendingType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, poolsCount, threads, true, false);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ TThreadParkPad pad;
+ TAtomic actorsAlive = 0;
+ double elapsedTime = 0;
+ ui32 followerPoolId = 0;
+
+ ui32 leaderPoolId = poolsCount == 1 ? 0 : 1;
+ ui64 eventsPerPair = TSettings::TotalEventsAmountPerThread;
+
+ TActorId followerId = actorSystem.Register(
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OtherEvents=eventsPerPair / 2, .Allocation=allocation}
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
+ THolder<IActor> leader{
+ new TTestEndDecorator(
+ THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OwnEvents=eventsPerPair / 2,
+ .ElapsedTime=&elapsedTime,
+ .Receivers={followerId},
+ .Allocation=allocation,
+ .SendingType=sendingType,
+ }
+ )),
+ &pad,
+ &actorsAlive
+ )
+ };
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
+
+ pad.Park();
+ actorSystem.Stop();
+
+ return 1e9 * elapsedTime;
+ }
+
+ static double BenchSendActivateReceiveWithMailboxNeighbours(ui32 MailboxNeighbourActors, EPoolType poolType, ESendingType sendingType) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ TThreadParkPad pad;
+ TAtomic actorsAlive = 0;
+ double elapsedTime = 0;
+
+ ui64 eventsPerPair = TSettings::TotalEventsAmountPerThread;
+
+ TActorId followerId = actorSystem.Register(
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OtherEvents=eventsPerPair / 2,
+ .Allocation=false,
+ .Neighbours=MailboxNeighbourActors,
+ }
+ ),
+ TMailboxType::HTSwap
+ );
+ THolder<IActor> leader{
+ new TTestEndDecorator(
+ THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OwnEvents=eventsPerPair / 2,
+ .ElapsedTime=&elapsedTime,
+ .Receivers={followerId},
+ .Allocation=false,
+ .SendingType=sendingType,
+ .Neighbours=MailboxNeighbourActors,
+ }
+ )),
+ &pad,
+ &actorsAlive
+ )
+ };
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap);
+
+ pad.Park();
+ actorSystem.Stop();
+
+ return 1e9 * elapsedTime;
+ }
+
+ struct TBenchResult {
+ double ElapsedTime;
+ ui64 SentEvents;
+ ui64 MinPairSentEvents;
+ ui64 MaxPairSentEvents;
+ };
+
+ static auto BenchContentedThreads(ui32 threads, ui32 actorsPairsCount, EPoolType poolType, ESendingType sendingType, TDuration testDuration = TDuration::Zero(), ui32 inFlight = 1) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, threads, false, false);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ TThreadParkPad pad;
+ TAtomic actorsAlive = 0;
+
+ TEventSharedCounters sharedCounters(actorsPairsCount);
+
+ ui64 totalEvents = TSettings::TotalEventsAmountPerThread * threads;
+ ui64 eventsPerPair = totalEvents / actorsPairsCount;
+
+ for (ui32 i = 0; i < actorsPairsCount; ++i) {
+ ui32 followerPoolId = 0;
+ ui32 leaderPoolId = 0;
+ TActorId followerId = actorSystem.Register(
+ new TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OtherEvents = eventsPerPair / 2,
+ .EndlessSending = bool(testDuration),
+ .Allocation = false,
+ .SharedCounters = &sharedCounters,
+ }
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
+ THolder<IActor> leader{
+ new TTestEndDecorator(
+ THolder(new TSendReceiveActor(TSendReceiveActorParams{
+ .OwnEvents = eventsPerPair / 2,
+ .EndlessSending = bool(testDuration),
+ .Receivers={followerId},
+ .Allocation = false,
+ .SendingType=sendingType,
+ .SharedCounters=&sharedCounters,
+ .InFlight = inFlight
+ }, i)),
+ &pad,
+ &actorsAlive
+ )
+ };
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
+ }
+
+ if (testDuration) {
+ Sleep(testDuration);
+ for (ui32 idx = 0; idx < actorsPairsCount; ++idx) {
+ sharedCounters.EndedCounters[idx].store(sharedCounters.Counters[idx]);
+ }
+ sharedCounters.EndTimeTs = GetCycleCountFast();
+ } else {
+ pad.Park();
+ }
+ actorSystem.Stop();
+
+ ui64 sentEvents = sharedCounters.EndedCounters[0] - sharedCounters.StartedCounters[0];
+ ui64 minSentEvents = sentEvents;
+ ui64 maxSentEvents = sentEvents;
+ for (ui32 pairIdx = 1; pairIdx < actorsPairsCount; ++pairIdx) {
+ ui64 count = sharedCounters.EndedCounters[pairIdx] - sharedCounters.StartedCounters[pairIdx];
+ sentEvents += count;
+ minSentEvents = ::Min(minSentEvents, count);
+ maxSentEvents = ::Max(maxSentEvents, count);
+ }
+
+ return TBenchResult {
+ .ElapsedTime = 1000 * Ts2Us(sharedCounters.EndTimeTs - sharedCounters.StartTimeTs),
+ .SentEvents = sentEvents,
+ .MinPairSentEvents = minSentEvents,
+ .MaxPairSentEvents = maxSentEvents
+ };
+ }
+
+ static auto BenchStarContentedThreads(ui32 threads, ui32 actorsPairsCount, EPoolType poolType, ESendingType sendingType, TDuration testDuration = TDuration::Zero(), ui32 starMultiply=10) {
+ THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, threads, true, false);
+ TActorSystem actorSystem(setup);
+ actorSystem.Start();
+
+ TThreadParkPad pad;
+ TAtomic actorsAlive = 0;
+
+ TEventSharedCounters sharedCounters(actorsPairsCount);
+
+ ui64 totalEvents = TSettings::TotalEventsAmountPerThread * threads;
+ ui64 eventsPerPair = totalEvents / actorsPairsCount;
+
+ for (ui32 i = 0; i < actorsPairsCount; ++i) {
+ ui32 followerPoolId = 0;
+ ui32 leaderPoolId = 0;
+ std::vector<TActorId> receivers;
+ for (ui32 idx = 0; idx < starMultiply; ++idx) {
+ TActorId followerId = actorSystem.Register(
+ new TSendReceiveActor(
+ TSendReceiveActorParams{
+ .OtherEvents = eventsPerPair / 2 / starMultiply,
+ .EndlessSending = bool(testDuration),
+ .Allocation = false,
+ .SharedCounters = &sharedCounters,
+ }
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
+ receivers.push_back(followerId);
+ }
+ THolder<IActor> leader{
+ new TTestEndDecorator(
+ THolder(new TSendReceiveActor(TSendReceiveActorParams{
+ .OwnEvents = eventsPerPair / 2,
+ .EndlessSending = bool(testDuration),
+ .Receivers=receivers,
+ .Allocation = false,
+ .SendingType=sendingType,
+ .SharedCounters=&sharedCounters,
+ }, i)),
+ &pad,
+ &actorsAlive
+ )
+ };
+ actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
+ }
+
+ if (testDuration) {
+ Sleep(testDuration);
+ for (ui32 idx = 0; idx < actorsPairsCount; ++idx) {
+ sharedCounters.EndedCounters[idx].store(sharedCounters.Counters[idx]);
+ }
+ sharedCounters.EndTimeTs = GetCycleCountFast();
+ } else {
+ pad.Park();
+ }
+ actorSystem.Stop();
+
+ ui64 sentEvents = sharedCounters.EndedCounters[0] - sharedCounters.StartedCounters[0];
+ ui64 minSentEvents = sentEvents;
+ ui64 maxSentEvents = sentEvents;
+ for (ui32 pairIdx = 1; pairIdx < actorsPairsCount; ++pairIdx) {
+ ui64 count = sharedCounters.EndedCounters[pairIdx] - sharedCounters.StartedCounters[pairIdx];
+ sentEvents += count;
+ minSentEvents = ::Min(minSentEvents, count);
+ maxSentEvents = ::Max(maxSentEvents, count);
+ }
+
+ return TBenchResult {
+ .ElapsedTime = 1000 * Ts2Us(sharedCounters.EndTimeTs - sharedCounters.StartTimeTs),
+ .SentEvents = sentEvents,
+ .MinPairSentEvents = minSentEvents,
+ .MaxPairSentEvents = maxSentEvents
+ };
+ }
+
+
+ static auto Mean(const std::vector<double>& data) {
+ return Accumulate(data.begin(), data.end(), 0.0) / data.size();
+ }
+
+ static auto Deviation(const std::vector<double>& data) {
+ auto mean = Mean(data);
+ double deviation = 0.0;
+ for (const auto& x : data) {
+ deviation += (x - mean) * (x - mean);
+ }
+ return std::sqrt(deviation / data.size());
+ }
+
+ static double Min(const std::vector<double>& data) {
+ return *std::min_element(data.begin(), data.end());
+ }
+
+ static double Max(const std::vector<double>& data) {
+ return *std::max_element(data.begin(), data.end());
+ }
+
+ template <auto Measurment>
+ struct TStats {
+ double Mean;
+ double Deviation;
+ double Min;
+ double Max;
+
+ TStats(const std::vector<double> &data)
+ : Mean(TActorBenchmark::Mean(data))
+ , Deviation(TActorBenchmark::Deviation(data))
+ , Min(TActorBenchmark::Min(data))
+ , Max(TActorBenchmark::Max(data))
+ {
+ }
+
+ TString ToString() {
+ return TStringBuilder() << Mean << " ± " << Deviation << " " << Measurment()
+ << " " << std::ceil(Deviation / Mean * 1000) / 10.0 << "%"
+ << " min " << Min << " " << Measurment() << " max " << Max << " " << Measurment();
+ }
+ };
+
+ static constexpr auto EmptyMsr = []{return "";};
+ static constexpr auto NsMsr = []{return "ns";};
+
+ struct TStatsBenchResult {
+ TStats<NsMsr> ElapsedTime;
+ TStats<EmptyMsr> SentEvents;
+ TStats<EmptyMsr> MinPairSentEvents;
+ TStats<EmptyMsr> MaxPairSentEvents;
+
+ TString ToString() {
+ return TStringBuilder() << ElapsedTime.ToString() << Endl << SentEvents.ToString() << Endl << MinPairSentEvents.ToString() << Endl << MaxPairSentEvents.ToString();
+ }
+ };
+
+ template <typename Func>
+ static auto CountStats(Func func, ui32 itersCount = 5) {
+ if constexpr (std::is_same_v<double, std::decay_t<decltype(func())>>) {
+ std::vector<double> elapsedTimes;
+ for (ui32 i = 0; i < itersCount; ++i) {
+ auto elapsedTime = func();
+ elapsedTimes.push_back(elapsedTime);
+ }
+ return TStats<NsMsr>(elapsedTimes);
+ } else {
+ std::vector<double> elapsedTimes;
+ std::vector<double> sentEvents;
+ std::vector<double> minPairSentEvents;
+ std::vector<double> maxPairSentEvents;
+ for (ui32 i = 0; i < itersCount; ++i) {
+ TBenchResult result = func();
+ elapsedTimes.push_back(result.ElapsedTime);
+ sentEvents.push_back(result.SentEvents);
+ minPairSentEvents.push_back(result.MinPairSentEvents);
+ maxPairSentEvents.push_back(result.MaxPairSentEvents);
+ }
+ return TStatsBenchResult {
+ .ElapsedTime = TStats<NsMsr>(elapsedTimes),
+ .SentEvents = TStats<EmptyMsr>(sentEvents),
+ .MinPairSentEvents = TStats<EmptyMsr>(minPairSentEvents),
+ .MaxPairSentEvents = TStats<EmptyMsr>(maxPairSentEvents),
+ };
+ }
+ }
+
+ static void RunBenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType) {
+ auto stats = CountStats([=] {
+ return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Common);
+ });
+ Cerr << stats.ToString() << Endl;
+ stats = CountStats([=] {
+ return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Lazy);
+ });
+ Cerr << stats.ToString() << " Lazy" << Endl;
+ stats = CountStats([=] {
+ return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Tail);
+ });
+ Cerr << stats.ToString() << " Tail" << Endl;
+ }
+
+ static void RunBenchContentedThreads(ui32 threads, EPoolType poolType) {
+ for (ui32 actorPairs = 1; actorPairs <= 2 * threads; actorPairs++) {
+ auto stats = CountStats([threads, actorPairs, poolType] {
+ return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Common);
+ });
+ Cerr << stats.ToString() << " actorPairs: " << actorPairs << Endl;
+ stats = CountStats([threads, actorPairs, poolType] {
+ return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Lazy);
+ });
+ Cerr << stats.ToString() << " actorPairs: " << actorPairs << " Lazy"<< Endl;
+ stats = CountStats([threads, actorPairs, poolType] {
+ return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Tail);
+ });
+ Cerr << stats.ToString() << " actorPairs: " << actorPairs << " Tail"<< Endl;
+ }
+ }
+
+ static void RunSendActivateReceiveCSV(const std::vector<ui32> &threadsList, const std::vector<ui32> &actorPairsList, const std::vector<ui32> &inFlights) {
+ Cout << "threads,actorPairs,in_flight,msgs_per_sec,elapsed_seconds,min_pair_sent_msgs,max_pair_sent_msgs" << Endl;
+ for (ui32 threads : threadsList) {
+ for (ui32 actorPairs : actorPairsList) {
+ for (ui32 inFlight : inFlights) {
+ auto stats = CountStats([threads, actorPairs, inFlight] {
+ return BenchContentedThreads(threads, actorPairs, EPoolType::Basic, ESendingType::Common, TDuration::Seconds(1), inFlight);
+ }, 3);
+ double elapsedSeconds = stats.ElapsedTime.Mean / 1e9;
+ ui64 eventsPerSecond = stats.SentEvents.Mean / elapsedSeconds;
+ Cout << threads << "," << actorPairs << "," << inFlight << "," << eventsPerSecond << "," << elapsedSeconds << "," << stats.MinPairSentEvents.Min << "," << stats.MaxPairSentEvents.Max << Endl;
+ }
+ }
+ }
+ }
+
+
+ static void RunStarSendActivateReceiveCSV(const std::vector<ui32> &threadsList, const std::vector<ui32> &actorPairsList, const std::vector<ui32> &starsList) {
+ Cout << "threads,actorPairs,star_multiply,msgs_per_sec,elapsed_seconds,min_pair_sent_msgs,max_pair_sent_msgs" << Endl;
+ for (ui32 threads : threadsList) {
+ for (ui32 actorPairs : actorPairsList) {
+ for (ui32 stars : starsList) {
+ auto stats = CountStats([threads, actorPairs, stars] {
+ return BenchStarContentedThreads(threads, actorPairs, EPoolType::Basic, ESendingType::Common, TDuration::Seconds(1), stars);
+ }, 3);
+ double elapsedSeconds = stats.ElapsedTime.Mean / 1e9;
+ ui64 eventsPerSecond = stats.SentEvents.Mean / elapsedSeconds;
+ Cout << threads << "," << actorPairs << "," << stars << "," << eventsPerSecond << "," << elapsedSeconds << "," << stats.MinPairSentEvents.Min << "," << stats.MaxPairSentEvents.Max << Endl;
+ }
+ }
+ }
+ }
+};
+
+} // NActors::NTests
diff --git a/library/cpp/actors/core/actor_ut.cpp b/library/cpp/actors/core/actor_ut.cpp
index 0d0721fae3e..b1e681c1ec8 100644
--- a/library/cpp/actors/core/actor_ut.cpp
+++ b/library/cpp/actors/core/actor_ut.cpp
@@ -1,9 +1,10 @@
-#include "actor.cpp"
+#include "actor.h"
#include "events.h"
#include "actorsystem.h"
#include "executor_pool_basic.h"
#include "scheduler_basic.h"
#include "actor_bootstrapped.h"
+#include "actor_benchmark_helper.h"
#include <library/cpp/actors/testlib/test_runtime.h>
#include <library/cpp/actors/util/threadparkpad.h>
@@ -15,336 +16,18 @@
#include <util/system/hp_timer.h>
using namespace NActors;
-
-struct TTestEndDecorator : TDecorator {
- TThreadParkPad* Pad;
- TAtomic* ActorsAlive;
-
- TTestEndDecorator(THolder<IActor>&& actor, TThreadParkPad* pad, TAtomic* actorsAlive)
- : TDecorator(std::move(actor))
- , Pad(pad)
- , ActorsAlive(actorsAlive)
- {
- AtomicIncrement(*ActorsAlive);
- }
-
- ~TTestEndDecorator() {
- if (AtomicDecrement(*ActorsAlive) == 0) {
- Pad->Unpark();
- }
- }
-};
+using namespace NActors::NTests;
Y_UNIT_TEST_SUITE(ActorBenchmark) {
- static constexpr bool DefaultNoRealtime = true;
- static constexpr ui32 DefaultSpinThreshold = 1000000;
- static constexpr ui32 TotalEventsAmount = 1000;
-
- class TDummyActor : public TActor<TDummyActor> {
- public:
- TDummyActor() : TActor<TDummyActor>(&TDummyActor::StateFunc) {}
- STFUNC(StateFunc) {
- (void)ev;
- }
- };
-
- enum class ERole {
- Leader,
- Follower
- };
-
- class TSendReceiveActor : public TActorBootstrapped<TSendReceiveActor> {
- public:
- static constexpr auto ActorActivityType() {
- return EActivityType::ACTORLIB_COMMON;
- }
-
- TSendReceiveActor(double* elapsedTime, TActorId receiver, bool allocation, ERole role, ESendingType sendingType, ui32 neighbours = 0)
- : EventsCounter(TotalEventsAmount)
- , ElapsedTime(elapsedTime)
- , Receiver(receiver)
- , AllocatesMemory(allocation)
- , Role(role)
- , SendingType(sendingType)
- , MailboxNeighboursCount(neighbours)
- {}
-
- void Bootstrap(const TActorContext &ctx) {
- if (!Receiver && Role == ERole::Leader) {
- this->Receiver = SelfId();
- } else {
- EventsCounter /= 2; // We want to measure CPU requirement for one-way send
- }
- Timer.Reset();
- Become(&TThis::StateFunc);
- for (ui32 i = 0; i < MailboxNeighboursCount; ++i) {
- ctx.RegisterWithSameMailbox(new TDummyActor());
- }
- if (Role == ERole::Leader) {
- TAutoPtr<IEventHandle> ev = new IEventHandle(Receiver, SelfId(), new TEvents::TEvPing());
- SpecialSend(ev, ctx);
- }
- }
-
- void SpecialSend(TAutoPtr<IEventHandle> ev, const TActorContext &ctx) {
- --EventsCounter;
- if (SendingType == ESendingType::Lazy) {
- ctx.Send<ESendingType::Lazy>(ev);
- } else if (SendingType == ESendingType::Tail) {
- ctx.Send<ESendingType::Tail>(ev);
- } else {
- ctx.Send(ev);
- }
- }
-
- bool CheckWorkIsDone() {
- if (EventsCounter == 0) {
- if (ElapsedTime != nullptr) {
- *ElapsedTime = Timer.Passed() / TotalEventsAmount;
- }
- PassAway();
- return true;
- }
- return false;
- }
- STFUNC(StateFunc) {
- if (CheckWorkIsDone())
- return;
-
- auto ctx(ActorContext());
- if (AllocatesMemory) {
- SpecialSend(new IEventHandle(ev->Sender, SelfId(), new TEvents::TEvPing()), ctx);
- } else {
- std::swap(*const_cast<TActorId*>(&ev->Sender), *const_cast<TActorId*>(&ev->Recipient));
- ev->DropRewrite();
- SpecialSend(ev, ctx);
- }
-
- CheckWorkIsDone();
- }
-
- private:
- THPTimer Timer;
- ui64 EventsCounter;
- double* ElapsedTime;
- TActorId Receiver;
- bool AllocatesMemory;
- ERole Role;
- ESendingType SendingType;
- ui32 MailboxNeighboursCount;
- };
-
- void AddBasicPool(THolder<TActorSystemSetup>& setup, ui32 threads, bool activateEveryEvent, i16 sharedExecutorsCount) {
- TBasicExecutorPoolConfig basic;
- basic.PoolId = setup->GetExecutorsCount();
- basic.PoolName = TStringBuilder() << "b" << basic.PoolId;
- basic.Threads = threads;
- basic.SpinThreshold = DefaultSpinThreshold;
- basic.TimePerMailbox = TDuration::Hours(1);
- basic.SharedExecutorsCount = sharedExecutorsCount;
- basic.SoftProcessingDurationTs = Us2Ts(100);
- if (activateEveryEvent) {
- basic.EventsPerMailbox = 1;
- } else {
- basic.EventsPerMailbox = Max<ui32>();
- }
- setup->CpuManager.Basic.emplace_back(std::move(basic));
- }
-
- void AddUnitedPool(THolder<TActorSystemSetup>& setup, ui32 concurrency, bool activateEveryEvent) {
- TUnitedExecutorPoolConfig united;
- united.PoolId = setup->GetExecutorsCount();
- united.PoolName = TStringBuilder() << "u" << united.PoolId;
- united.Concurrency = concurrency;
- united.TimePerMailbox = TDuration::Hours(1);
- if (activateEveryEvent) {
- united.EventsPerMailbox = 1;
- } else {
- united.EventsPerMailbox = Max<ui32>();
- }
- setup->CpuManager.United.emplace_back(std::move(united));
- }
-
- THolder<TActorSystemSetup> GetActorSystemSetup(ui32 unitedCpuCount, bool preemption) {
- auto setup = MakeHolder<NActors::TActorSystemSetup>();
- setup->NodeId = 1;
- setup->CpuManager.UnitedWorkers.CpuCount = unitedCpuCount;
- setup->CpuManager.UnitedWorkers.SpinThresholdUs = DefaultSpinThreshold;
- setup->CpuManager.UnitedWorkers.NoRealtime = DefaultNoRealtime;
- if (preemption) {
- setup->CpuManager.UnitedWorkers.PoolLimitUs = 500;
- setup->CpuManager.UnitedWorkers.EventLimitUs = 100;
- setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 100;
- } else {
- setup->CpuManager.UnitedWorkers.PoolLimitUs = 100'000'000'000;
- setup->CpuManager.UnitedWorkers.EventLimitUs = 10'000'000'000;
- setup->CpuManager.UnitedWorkers.LimitPrecisionUs = 10'000'000'000;
- }
- setup->Scheduler = new TBasicSchedulerThread(NActors::TSchedulerConfig(512, 0));
- return setup;
- }
-
- enum class EPoolType {
- Basic,
- United
- };
-
- THolder<TActorSystemSetup> InitActorSystemSetup(EPoolType poolType, ui32 poolsCount, ui32 threads, bool activateEveryEvent, bool preemption) {
- if (poolType == EPoolType::Basic) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
- for (ui32 i = 0; i < poolsCount; ++i) {
- AddBasicPool(setup, threads, activateEveryEvent, 0);
- }
- return setup;
- } else if (poolType == EPoolType::United) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(poolsCount * threads, preemption);
- for (ui32 i = 0; i < poolsCount; ++i) {
- AddUnitedPool(setup, threads, activateEveryEvent);
- }
- return setup;
- }
- Y_FAIL();
- }
-
- double BenchSendReceive(bool allocation, NActors::TMailboxType::EType mType, EPoolType poolType, ESendingType sendingType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- TThreadParkPad pad;
- TAtomic actorsAlive = 0;
- double elapsedTime = 0;
- THolder<IActor> endActor{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(&elapsedTime, {}, allocation, ERole::Leader, sendingType)), &pad, &actorsAlive)};
-
- actorSystem.Register(endActor.Release(), mType);
-
- pad.Park();
- actorSystem.Stop();
-
- return 1e9 * elapsedTime;
- }
-
- double BenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType, ESendingType sendingType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, poolsCount, threads, true, false);
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- TThreadParkPad pad;
- TAtomic actorsAlive = 0;
- double elapsedTime = 0;
- ui32 followerPoolId = 0;
-
- ui32 leaderPoolId = poolsCount == 1 ? 0 : 1;
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, allocation, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
- THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(&elapsedTime, followerId, allocation, ERole::Leader, sendingType)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
-
- pad.Park();
- actorSystem.Stop();
-
- return 1e9 * elapsedTime;
- }
-
- double BenchSendActivateReceiveWithMailboxNeighbours(ui32 MailboxNeighbourActors, EPoolType poolType, ESendingType sendingType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, 1, false, false);
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- TThreadParkPad pad;
- TAtomic actorsAlive = 0;
- double elapsedTime = 0;
-
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, false, ERole::Follower, ESendingType::Common, MailboxNeighbourActors), TMailboxType::HTSwap);
- THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(&elapsedTime, followerId, false, ERole::Leader, sendingType, MailboxNeighbourActors)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap);
-
- pad.Park();
- actorSystem.Stop();
-
- return 1e9 * elapsedTime;
- }
-
- double BenchContentedThreads(ui32 threads, ui32 actorsPairsCount, EPoolType poolType, ESendingType sendingType) {
- THolder<TActorSystemSetup> setup = InitActorSystemSetup(poolType, 1, threads, true, false);
- TActorSystem actorSystem(setup);
- actorSystem.Start();
-
- TThreadParkPad pad;
- TAtomic actorsAlive = 0;
- THPTimer Timer;
-
- TVector<double> dummy(actorsPairsCount);
- Timer.Reset();
- for (ui32 i = 0; i < actorsPairsCount; ++i) {
- ui32 followerPoolId = 0;
- ui32 leaderPoolId = 0;
- TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
- THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(&dummy[i], followerId, true, ERole::Leader, sendingType)), &pad, &actorsAlive)};
- actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
- }
-
- pad.Park();
- auto elapsedTime = Timer.Passed() / TotalEventsAmount;
- actorSystem.Stop();
-
- return 1e9 * elapsedTime;
- }
-
- auto Mean(const TVector<double>& data) {
- return Accumulate(data.begin(), data.end(), 0.0) / data.size();
- }
-
- auto Deviation(const TVector<double>& data) {
- auto mean = Mean(data);
- double deviation = 0.0;
- for (const auto& x : data) {
- deviation += (x - mean) * (x - mean);
- }
- return std::sqrt(deviation / data.size());
- }
-
- struct TStats {
- double Mean;
- double Deviation;
- TString ToString() {
- return TStringBuilder() << Mean << " ± " << Deviation << " ns " << std::ceil(Deviation / Mean * 1000) / 10.0 << "%";
- }
- };
-
- template <typename Func>
- TStats CountStats(Func func, ui32 itersCount = 5) {
- TVector<double> elapsedTimes;
- for (ui32 i = 0; i < itersCount; ++i) {
- auto elapsedTime = func();
- elapsedTimes.push_back(elapsedTime);
- }
- return {Mean(elapsedTimes), Deviation(elapsedTimes)};
- }
-
- TVector<NActors::TMailboxType::EType> MailboxTypes = {
- TMailboxType::Simple,
- TMailboxType::Revolving,
- TMailboxType::HTSwap,
- TMailboxType::ReadAsFilled,
- TMailboxType::TinyReadAsFilled
- };
+ using TActorBenchmark = ::NActors::NTests::TActorBenchmark<>;
+ using TSettings = TActorBenchmark::TSettings;
+ using TSendReceiveActorParams = TActorBenchmark::TSendReceiveActorParams;
Y_UNIT_TEST(WithSharedExecutors) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
- AddBasicPool(setup, 2, 1, 0);
- AddBasicPool(setup, 2, 1, 1);
+ THolder<TActorSystemSetup> setup = TActorBenchmark::GetActorSystemSetup(0, false);
+ TActorBenchmark::AddBasicPool(setup, 2, 1, 0);
+ TActorBenchmark::AddBasicPool(setup, 2, 1, 1);
TActorSystem actorSystem(setup);
actorSystem.Start();
@@ -353,39 +36,61 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
TAtomic actorsAlive = 0;
THPTimer Timer;
+ ui64 eventsPerPair = TSettings::TotalEventsAmountPerThread * 4 / 60;
+
Timer.Reset();
for (ui32 i = 0; i < 50; ++i) {
ui32 followerPoolId = 0;
ui32 leaderPoolId = 0;
TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OtherEvents=eventsPerPair / 2, .Allocation=true}
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(nullptr, followerId, true, ERole::Leader, ESendingType::Common)), &pad, &actorsAlive)};
+ new TTestEndDecorator(THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OwnEvents=eventsPerPair / 2, .Receivers={followerId}, .Allocation=true}
+ )),
+ &pad,
+ &actorsAlive)
+ };
actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
}
for (ui32 i = 0; i < 10; ++i) {
ui32 followerPoolId = 1;
ui32 leaderPoolId = 1;
TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OtherEvents=eventsPerPair / 2, .Allocation=true}
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(nullptr, followerId, true, ERole::Leader, ESendingType::Common)), &pad, &actorsAlive)};
+ new TTestEndDecorator(
+ THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OwnEvents=eventsPerPair / 2, .Receivers={followerId}, .Allocation=true}
+ )),
+ &pad,
+ &actorsAlive
+ )
+ };
actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
}
pad.Park();
- auto elapsedTime = Timer.Passed() / TotalEventsAmount;
+ auto elapsedTime = Timer.Passed() / (TSettings::TotalEventsAmountPerThread * 4);
actorSystem.Stop();
Cerr << "Completed " << 1e9 * elapsedTime << Endl;
}
Y_UNIT_TEST(WithoutSharedExecutors) {
- THolder<TActorSystemSetup> setup = GetActorSystemSetup(0, false);
- AddBasicPool(setup, 2, 1, 0);
- AddBasicPool(setup, 2, 1, 0);
+ THolder<TActorSystemSetup> setup = TActorBenchmark::GetActorSystemSetup(0, false);
+ TActorBenchmark::AddBasicPool(setup, 2, 1, 0);
+ TActorBenchmark::AddBasicPool(setup, 2, 1, 0);
TActorSystem actorSystem(setup);
actorSystem.Start();
@@ -394,225 +99,217 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
TAtomic actorsAlive = 0;
THPTimer Timer;
+ ui64 eventsPerPair = TSettings::TotalEventsAmountPerThread * 4 / 60;
+
Timer.Reset();
for (ui32 i = 0; i < 50; ++i) {
ui32 followerPoolId = 0;
ui32 leaderPoolId = 0;
TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OtherEvents=eventsPerPair / 2, .Allocation=true}
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(nullptr, followerId, true, ERole::Leader, ESendingType::Common)), &pad, &actorsAlive)};
+ new TTestEndDecorator(
+ THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OwnEvents=eventsPerPair / 2, .Receivers={followerId}, .Allocation=true}
+ )),
+ &pad,
+ &actorsAlive
+ )
+ };
actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
}
for (ui32 i = 0; i < 10; ++i) {
ui32 followerPoolId = 1;
ui32 leaderPoolId = 1;
TActorId followerId = actorSystem.Register(
- new TSendReceiveActor(nullptr, {}, true, ERole::Follower, ESendingType::Common), TMailboxType::HTSwap, followerPoolId);
+ new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OtherEvents=eventsPerPair / 2, .Allocation=true}
+ ),
+ TMailboxType::HTSwap,
+ followerPoolId
+ );
THolder<IActor> leader{
- new TTestEndDecorator(THolder(
- new TSendReceiveActor(nullptr, followerId, true, ERole::Leader, ESendingType::Common)), &pad, &actorsAlive)};
+ new TTestEndDecorator(
+ THolder(new TActorBenchmark::TSendReceiveActor(
+ TSendReceiveActorParams{.OwnEvents=eventsPerPair / 2, .Receivers={followerId}, .Allocation=true}
+ )),
+ &pad,
+ &actorsAlive
+ )
+ };
actorSystem.Register(leader.Release(), TMailboxType::HTSwap, leaderPoolId);
}
pad.Park();
- auto elapsedTime = Timer.Passed() / TotalEventsAmount;
+ auto elapsedTime = Timer.Passed() / (4 * TSettings::TotalEventsAmountPerThread);
actorSystem.Stop();
Cerr << "Completed " << 1e9 * elapsedTime << Endl;
}
Y_UNIT_TEST(SendReceive1Pool1ThreadAlloc) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::Basic, ESendingType::Common);
+ for (const auto& mType : TSettings::MailboxTypes) {
+ auto stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Common);
});
Cerr << stats.ToString() << " " << mType << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::Basic, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Lazy);
});
Cerr << stats.ToString() << " " << mType << " Lazy" << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::Basic, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Tail);
});
Cerr << stats.ToString() << " " << mType << " Tail" << Endl;
}
}
Y_UNIT_TEST(SendReceive1Pool1ThreadAllocUnited) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::United, ESendingType::Common);
+ for (const auto& mType : TSettings::MailboxTypes) {
+ auto stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::United, ESendingType::Common);
});
Cerr << stats.ToString() << " " << mType << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::United, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::United, ESendingType::Lazy);
});
Cerr << stats.ToString() << " " << mType << " Lazy" << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(true, mType, EPoolType::United, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(true, mType, TActorBenchmark::EPoolType::United, ESendingType::Tail);
});
Cerr << stats.ToString() << " " << mType << " Tail" << Endl;
}
}
Y_UNIT_TEST(SendReceive1Pool1ThreadNoAlloc) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::Basic, ESendingType::Common);
+ for (const auto& mType : TSettings::MailboxTypes) {
+ auto stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Common);
});
Cerr << stats.ToString() << " " << mType << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::Basic, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Lazy);
});
Cerr << stats.ToString() << " " << mType << " Lazy" << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::Basic, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::Basic, ESendingType::Tail);
});
Cerr << stats.ToString() << " " << mType << " Tail" << Endl;
}
}
Y_UNIT_TEST(SendReceive1Pool1ThreadNoAllocUnited) {
- for (const auto& mType : MailboxTypes) {
- auto stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::United, ESendingType::Common);
+ for (const auto& mType : TSettings::MailboxTypes) {
+ auto stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::United, ESendingType::Common);
});
Cerr << stats.ToString() << " " << mType << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::United, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::United, ESendingType::Lazy);
});
Cerr << stats.ToString() << " " << mType << " Lazy" << Endl;
- stats = CountStats([mType] {
- return BenchSendReceive(false, mType, EPoolType::United, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([mType] {
+ return TActorBenchmark::BenchSendReceive(false, mType, TActorBenchmark::EPoolType::United, ESendingType::Tail);
});
Cerr << stats.ToString() << " " << mType << " Tail" << Endl;
}
}
- void RunBenchSendActivateReceive(ui32 poolsCount, ui32 threads, bool allocation, EPoolType poolType) {
- auto stats = CountStats([=] {
- return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Common);
- });
- Cerr << stats.ToString() << Endl;
- stats = CountStats([=] {
- return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Lazy);
- });
- Cerr << stats.ToString() << " Lazy" << Endl;
- stats = CountStats([=] {
- return BenchSendActivateReceive(poolsCount, threads, allocation, poolType, ESendingType::Tail);
- });
- Cerr << stats.ToString() << " Tail" << Endl;
- }
-
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadAlloc) {
- RunBenchSendActivateReceive(1, 1, true, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 1, true, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadAllocUnited) {
- RunBenchSendActivateReceive(1, 1, true, EPoolType::United);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 1, true, TActorBenchmark::EPoolType::United);
}
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadNoAlloc) {
- RunBenchSendActivateReceive(1, 1, false, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 1, false, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive1Pool1ThreadNoAllocUnited) {
- RunBenchSendActivateReceive(1, 1, false, EPoolType::United);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 1, false, TActorBenchmark::EPoolType::United);
}
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsAlloc) {
- RunBenchSendActivateReceive(1, 2, true, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 2, true, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsAllocUnited) {
- RunBenchSendActivateReceive(1, 2, true, EPoolType::United);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 2, true, TActorBenchmark::EPoolType::United);
}
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsNoAlloc) {
- RunBenchSendActivateReceive(1, 2, false, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 2, false, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsNoAllocUnited) {
- RunBenchSendActivateReceive(1, 2, false, EPoolType::United);
+ TActorBenchmark::RunBenchSendActivateReceive(1, 2, false, TActorBenchmark::EPoolType::United);
}
Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAlloc) {
- RunBenchSendActivateReceive(2, 1, true, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(2, 1, true, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive2Pool1ThreadAllocUnited) {
- RunBenchSendActivateReceive(2, 1, true, EPoolType::United);
+ TActorBenchmark::RunBenchSendActivateReceive(2, 1, true, TActorBenchmark::EPoolType::United);
}
Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAlloc) {
- RunBenchSendActivateReceive(2, 1, false, EPoolType::Basic);
+ TActorBenchmark::RunBenchSendActivateReceive(2, 1, false, TActorBenchmark::EPoolType::Basic);
}
Y_UNIT_TEST(SendActivateReceive2Pool1ThreadNoAllocUnited) {
- RunBenchSendActivateReceive(2, 1, false, EPoolType::United);
- }
-
- void RunBenchContentedThreads(ui32 threads, EPoolType poolType) {
- for (ui32 actorPairs = 1; actorPairs <= 2 * threads; actorPairs++) {
- auto stats = CountStats([threads, actorPairs, poolType] {
- return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Common);
- });
- Cerr << stats.ToString() << " actorPairs: " << actorPairs << Endl;
- stats = CountStats([threads, actorPairs, poolType] {
- return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Lazy);
- });
- Cerr << stats.ToString() << " actorPairs: " << actorPairs << " Lazy"<< Endl;
- stats = CountStats([threads, actorPairs, poolType] {
- return BenchContentedThreads(threads, actorPairs, poolType, ESendingType::Tail);
- });
- Cerr << stats.ToString() << " actorPairs: " << actorPairs << " Tail"<< Endl;
- }
- }
-
- Y_UNIT_TEST(SendActivateReceive1Pool1Threads) { RunBenchContentedThreads(1, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool1ThreadsUnited) { RunBenchContentedThreads(1, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool2Threads) { RunBenchContentedThreads(2, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsUnited) { RunBenchContentedThreads(2, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool3Threads) { RunBenchContentedThreads(3, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool3ThreadsUnited) { RunBenchContentedThreads(3, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool4Threads) { RunBenchContentedThreads(4, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool4ThreadsUnited) { RunBenchContentedThreads(4, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool5Threads) { RunBenchContentedThreads(5, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool5ThreadsUnited) { RunBenchContentedThreads(5, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool6Threads) { RunBenchContentedThreads(6, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool6ThreadsUnited) { RunBenchContentedThreads(6, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool7Threads) { RunBenchContentedThreads(7, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool7ThreadsUnited) { RunBenchContentedThreads(7, EPoolType::United); }
- Y_UNIT_TEST(SendActivateReceive1Pool8Threads) { RunBenchContentedThreads(8, EPoolType::Basic); }
- Y_UNIT_TEST(SendActivateReceive1Pool8ThreadsUnited) { RunBenchContentedThreads(8, EPoolType::United); }
+ TActorBenchmark::RunBenchSendActivateReceive(2, 1, false, TActorBenchmark::EPoolType::United);
+ }
+
+ Y_UNIT_TEST(SendActivateReceive1Pool1Threads) { TActorBenchmark::RunBenchContentedThreads(1, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool1ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(1, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool2Threads) { TActorBenchmark::RunBenchContentedThreads(2, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool2ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(2, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool3Threads) { TActorBenchmark::RunBenchContentedThreads(3, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool3ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(3, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool4Threads) { TActorBenchmark::RunBenchContentedThreads(4, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool4ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(4, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool5Threads) { TActorBenchmark::RunBenchContentedThreads(5, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool5ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(5, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool6Threads) { TActorBenchmark::RunBenchContentedThreads(6, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool6ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(6, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool7Threads) { TActorBenchmark::RunBenchContentedThreads(7, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool7ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(7, TActorBenchmark::EPoolType::United); }
+ Y_UNIT_TEST(SendActivateReceive1Pool8Threads) { TActorBenchmark::RunBenchContentedThreads(8, TActorBenchmark::EPoolType::Basic); }
+ Y_UNIT_TEST(SendActivateReceive1Pool8ThreadsUnited) { TActorBenchmark::RunBenchContentedThreads(8, TActorBenchmark::EPoolType::United); }
Y_UNIT_TEST(SendActivateReceiveCSV) {
- Cout << "threads,actorPairs,msgs_per_sec" << Endl;
+ std::vector<ui32> threadsList;
for (ui32 threads = 1; threads <= 32; threads *= 2) {
- for (ui32 actorPairs = 1; actorPairs <= 2 * 32; actorPairs *= 2) {
- auto stats = CountStats([threads, actorPairs] {
- return BenchContentedThreads(threads, actorPairs, EPoolType::Basic, ESendingType::Common);
- }, 3);
- Cout << threads << "," << actorPairs << "," << actorPairs * 1e9 / stats.Mean << Endl;
- }
+ threadsList.push_back(threads);
+ }
+ std::vector<ui32> actorPairsList;
+ for (ui32 actorPairs = 1; actorPairs <= 2 * 32; actorPairs *= 2) {
+ actorPairsList.push_back(actorPairs);
}
+ TActorBenchmark::RunSendActivateReceiveCSV(threadsList, actorPairsList, {1});
}
Y_UNIT_TEST(SendActivateReceiveWithMailboxNeighbours) {
TVector<ui32> NeighbourActors = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256};
for (const auto& neighbour : NeighbourActors) {
- auto stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::Basic, ESendingType::Common);
+ auto stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::Basic, ESendingType::Common);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
- stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::Basic, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::Basic, ESendingType::Lazy);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << " Lazy" << Endl;
- stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::Basic, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::Basic, ESendingType::Tail);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << " Tail" << Endl;
}
@@ -621,16 +318,16 @@ Y_UNIT_TEST_SUITE(ActorBenchmark) {
Y_UNIT_TEST(SendActivateReceiveWithMailboxNeighboursUnited) {
TVector<ui32> NeighbourActors = {0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256};
for (const auto& neighbour : NeighbourActors) {
- auto stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::United, ESendingType::Common);
+ auto stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::United, ESendingType::Common);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << Endl;
- stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::United, ESendingType::Lazy);
+ stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::United, ESendingType::Lazy);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << " Lazy" << Endl;
- stats = CountStats([neighbour] {
- return BenchSendActivateReceiveWithMailboxNeighbours(neighbour, EPoolType::United, ESendingType::Tail);
+ stats = TActorBenchmark::CountStats([neighbour] {
+ return TActorBenchmark::BenchSendActivateReceiveWithMailboxNeighbours(neighbour, TActorBenchmark::EPoolType::United, ESendingType::Tail);
});
Cerr << stats.ToString() << " neighbourActors: " << neighbour << " Tail" << Endl;
}
diff --git a/library/cpp/actors/core/ut_fat/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/core/ut_fat/CMakeLists.darwin-x86_64.txt
new file mode 100644
index 00000000000..88a9860fc1e
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/CMakeLists.darwin-x86_64.txt
@@ -0,0 +1,71 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_executable(library-cpp-actors-core-ut_fat)
+target_link_libraries(library-cpp-actors-core-ut_fat PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+ library-cpp-cpuid_check
+ cpp-testing-unittest_main
+ cpp-actors-core
+)
+target_link_options(library-cpp-actors-core-ut_fat PRIVATE
+ -Wl,-platform_version,macos,11.0,11.0
+ -fPIC
+ -fPIC
+ -framework
+ CoreFoundation
+)
+target_sources(library-cpp-actors-core-ut_fat PRIVATE
+ ${CMAKE_SOURCE_DIR}/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
+)
+set_property(
+ TARGET
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ SPLIT_FACTOR
+ 20
+)
+add_yunittest(
+ NAME
+ library-cpp-actors-core-ut_fat
+ TEST_TARGET
+ library-cpp-actors-core-ut_fat
+ TEST_ARG
+ --print-before-suite
+ --print-before-test
+ --fork-tests
+ --print-times
+ --show-fails
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ LABELS
+ LARGE
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ PROCESSORS
+ 1
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ TIMEOUT
+ 1200
+)
+target_allocator(library-cpp-actors-core-ut_fat
+ system_allocator
+)
+vcs_info(library-cpp-actors-core-ut_fat)
diff --git a/library/cpp/actors/core/ut_fat/CMakeLists.linux-aarch64.txt b/library/cpp/actors/core/ut_fat/CMakeLists.linux-aarch64.txt
new file mode 100644
index 00000000000..653d98fe606
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,74 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_executable(library-cpp-actors-core-ut_fat)
+target_link_libraries(library-cpp-actors-core-ut_fat PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ yutil
+ cpp-testing-unittest_main
+ cpp-actors-core
+)
+target_link_options(library-cpp-actors-core-ut_fat PRIVATE
+ -ldl
+ -lrt
+ -Wl,--no-as-needed
+ -fPIC
+ -fPIC
+ -lpthread
+ -lrt
+ -ldl
+)
+target_sources(library-cpp-actors-core-ut_fat PRIVATE
+ ${CMAKE_SOURCE_DIR}/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
+)
+set_property(
+ TARGET
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ SPLIT_FACTOR
+ 20
+)
+add_yunittest(
+ NAME
+ library-cpp-actors-core-ut_fat
+ TEST_TARGET
+ library-cpp-actors-core-ut_fat
+ TEST_ARG
+ --print-before-suite
+ --print-before-test
+ --fork-tests
+ --print-times
+ --show-fails
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ LABELS
+ LARGE
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ PROCESSORS
+ 1
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ TIMEOUT
+ 1200
+)
+target_allocator(library-cpp-actors-core-ut_fat
+ cpp-malloc-jemalloc
+)
+vcs_info(library-cpp-actors-core-ut_fat)
diff --git a/library/cpp/actors/core/ut_fat/CMakeLists.linux-x86_64.txt b/library/cpp/actors/core/ut_fat/CMakeLists.linux-x86_64.txt
new file mode 100644
index 00000000000..e929e6f394b
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/CMakeLists.linux-x86_64.txt
@@ -0,0 +1,76 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_executable(library-cpp-actors-core-ut_fat)
+target_link_libraries(library-cpp-actors-core-ut_fat PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ yutil
+ library-cpp-cpuid_check
+ cpp-testing-unittest_main
+ cpp-actors-core
+)
+target_link_options(library-cpp-actors-core-ut_fat PRIVATE
+ -ldl
+ -lrt
+ -Wl,--no-as-needed
+ -fPIC
+ -fPIC
+ -lpthread
+ -lrt
+ -ldl
+)
+target_sources(library-cpp-actors-core-ut_fat PRIVATE
+ ${CMAKE_SOURCE_DIR}/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
+)
+set_property(
+ TARGET
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ SPLIT_FACTOR
+ 20
+)
+add_yunittest(
+ NAME
+ library-cpp-actors-core-ut_fat
+ TEST_TARGET
+ library-cpp-actors-core-ut_fat
+ TEST_ARG
+ --print-before-suite
+ --print-before-test
+ --fork-tests
+ --print-times
+ --show-fails
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ LABELS
+ LARGE
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ PROCESSORS
+ 1
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ TIMEOUT
+ 1200
+)
+target_allocator(library-cpp-actors-core-ut_fat
+ cpp-malloc-tcmalloc
+ libs-tcmalloc-no_percpu_cache
+)
+vcs_info(library-cpp-actors-core-ut_fat)
diff --git a/library/cpp/actors/core/ut_fat/CMakeLists.txt b/library/cpp/actors/core/ut_fat/CMakeLists.txt
new file mode 100644
index 00000000000..f8b31df0c11
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin-x86_64.txt)
+elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA)
+ include(CMakeLists.windows-x86_64.txt)
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA)
+ include(CMakeLists.linux-x86_64.txt)
+endif()
diff --git a/library/cpp/actors/core/ut_fat/CMakeLists.windows-x86_64.txt b/library/cpp/actors/core/ut_fat/CMakeLists.windows-x86_64.txt
new file mode 100644
index 00000000000..cd693cd949d
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/CMakeLists.windows-x86_64.txt
@@ -0,0 +1,64 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_executable(library-cpp-actors-core-ut_fat)
+target_link_libraries(library-cpp-actors-core-ut_fat PUBLIC
+ contrib-libs-cxxsupp
+ yutil
+ library-cpp-cpuid_check
+ cpp-testing-unittest_main
+ cpp-actors-core
+)
+target_sources(library-cpp-actors-core-ut_fat PRIVATE
+ ${CMAKE_SOURCE_DIR}/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
+)
+set_property(
+ TARGET
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ SPLIT_FACTOR
+ 20
+)
+add_yunittest(
+ NAME
+ library-cpp-actors-core-ut_fat
+ TEST_TARGET
+ library-cpp-actors-core-ut_fat
+ TEST_ARG
+ --print-before-suite
+ --print-before-test
+ --fork-tests
+ --print-times
+ --show-fails
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ LABELS
+ LARGE
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ PROCESSORS
+ 1
+)
+set_yunittest_property(
+ TEST
+ library-cpp-actors-core-ut_fat
+ PROPERTY
+ TIMEOUT
+ 1200
+)
+target_allocator(library-cpp-actors-core-ut_fat
+ system_allocator
+)
+vcs_info(library-cpp-actors-core-ut_fat)
diff --git a/library/cpp/actors/core/ut_fat/actor_benchmark.cpp b/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
new file mode 100644
index 00000000000..9512ee1adaf
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/actor_benchmark.cpp
@@ -0,0 +1,46 @@
+
+
+#include <library/cpp/actors/core/actor_benchmark_helper.h>
+
+#include <library/cpp/testing/unittest/registar.h>
+
+
+using namespace NActors;
+using namespace NActors::NTests;
+
+
+struct THeavyActorBenchmarkSettings : TActorBenchmarkSettings {
+ static constexpr ui32 TotalEventsAmountPerThread = 1'000'000;
+
+ static constexpr auto MailboxTypes = {
+ TMailboxType::HTSwap,
+ };
+};
+
+
+Y_UNIT_TEST_SUITE(HeavyActorBenchmark) {
+
+ using TActorBenchmark = ::NActors::NTests::TActorBenchmark<THeavyActorBenchmarkSettings>;
+ using TSettings = TActorBenchmark::TSettings;
+
+
+ Y_UNIT_TEST(SendActivateReceiveCSV) {
+ std::vector<ui32> threadsList;
+ for (ui32 threads = 1; threads <= 28; threads++) {
+ threadsList.push_back(threads);
+ }
+ std::vector<ui32> actorPairsList = {512};
+ TActorBenchmark::RunSendActivateReceiveCSV(threadsList, actorPairsList, {1,100, 200});
+ }
+
+ Y_UNIT_TEST(StarSendActivateReceiveCSV) {
+ std::vector<ui32> threadsList;
+ for (ui32 threads = 1; threads <= 28; threads++) {
+ threadsList.push_back(threads);
+ }
+ std::vector<ui32> actorPairsList = {512};
+ std::vector<ui32> starsList = {10};
+ TActorBenchmark::RunStarSendActivateReceiveCSV(threadsList, actorPairsList, starsList);
+ }
+
+}
diff --git a/library/cpp/actors/core/ut_fat/ya.make b/library/cpp/actors/core/ut_fat/ya.make
new file mode 100644
index 00000000000..937e59720da
--- /dev/null
+++ b/library/cpp/actors/core/ut_fat/ya.make
@@ -0,0 +1,32 @@
+UNITTEST()
+
+FORK_SUBTESTS()
+
+IF (SANITIZER_TYPE)
+ SIZE(LARGE)
+ TIMEOUT(2400)
+ TAG(ya:fat)
+ SPLIT_FACTOR(20)
+ REQUIREMENTS(
+ ram:32
+ )
+ELSE()
+ SIZE(LARGE)
+ TIMEOUT(1200)
+ TAG(ya:fat)
+ SPLIT_FACTOR(20)
+ REQUIREMENTS(
+ ram:16
+ )
+ENDIF()
+
+
+PEERDIR(
+ library/cpp/actors/core
+)
+
+SRCS(
+ actor_benchmark.cpp
+)
+
+END()
diff --git a/library/cpp/actors/core/ya.make b/library/cpp/actors/core/ya.make
index 649effd22f2..8dadea5fdcc 100644
--- a/library/cpp/actors/core/ya.make
+++ b/library/cpp/actors/core/ya.make
@@ -129,4 +129,5 @@ END()
RECURSE_FOR_TESTS(
ut
+ ut_fat
)