diff options
author | kruall <kruall@ydb.tech> | 2023-09-11 15:13:49 +0300 |
---|---|---|
committer | kruall <kruall@ydb.tech> | 2023-09-11 15:36:25 +0300 |
commit | 37785d3b5bb041cd4a7ca47f37dd374a87cdb97e (patch) | |
tree | af11a5a1012bf61bfe1743385965a09ee6e9549b /library/cpp | |
parent | 7e78e9674adeffb3b3b40c1cc58b022899b41409 (diff) | |
download | ydb-37785d3b5bb041cd4a7ca47f37dd374a87cdb97e.tar.gz |
Improve benchmarks, KIKIMR-19207
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/actors/core/CMakeLists.darwin-x86_64.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/core/CMakeLists.linux-aarch64.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/core/CMakeLists.linux-x86_64.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/core/CMakeLists.windows-x86_64.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/core/actor_benchmark_helper.h | 763 | ||||
-rw-r--r-- | library/cpp/actors/core/actor_ut.cpp | 601 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/CMakeLists.darwin-x86_64.txt | 71 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/CMakeLists.linux-aarch64.txt | 74 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/CMakeLists.linux-x86_64.txt | 76 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/CMakeLists.txt | 17 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/CMakeLists.windows-x86_64.txt | 64 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/actor_benchmark.cpp | 46 | ||||
-rw-r--r-- | library/cpp/actors/core/ut_fat/ya.make | 32 | ||||
-rw-r--r-- | library/cpp/actors/core/ya.make | 1 |
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 ¶ms, 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 ) |