Skip to content

Commit 53259c9

Browse files
kruallAleksandr Kriukov
andauthored
Add ring activation queue (#695)
Co-authored-by: Aleksandr Kriukov <kruall@ydb.ru>
1 parent 68184b7 commit 53259c9

File tree

5 files changed

+439
-2
lines changed

5 files changed

+439
-2
lines changed

ydb/library/actors/core/executor_pool_base.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ namespace NActors {
6969
: TExecutorPoolBaseMailboxed(poolId)
7070
, PoolThreads(threads)
7171
, ThreadsAffinity(affinity)
72+
#ifdef RING_ACTIVATION_QUEUE
73+
, Activations(threads == 1)
74+
#endif
7275
{}
7376

7477
TExecutorPoolBase::~TExecutorPoolBase() {
@@ -112,7 +115,11 @@ namespace NActors {
112115
}
113116

114117
void TExecutorPoolBase::ScheduleActivation(ui32 activation) {
118+
#ifdef RING_ACTIVATION_QUEUE
119+
ScheduleActivationEx(activation, 0);
120+
#else
115121
ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
122+
#endif
116123
}
117124

118125
Y_FORCE_INLINE bool IsAllowedToCapture(IExecutorPool *self) {
@@ -132,7 +139,11 @@ namespace NActors {
132139
TlsThreadContext->CapturedType = TlsThreadContext->SendingType;
133140
}
134141
if (activation) {
135-
ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
142+
#ifdef RING_ACTIVATION_QUEUE
143+
ScheduleActivationEx(activation, 0);
144+
#else
145+
ScheduleActivationEx(activation, AtomicIncrement(ActivationsRevolvingCounter));
146+
#endif
136147
}
137148
}
138149

ydb/library/actors/core/executor_pool_base.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44
#include "executor_thread.h"
55
#include "mon_stats.h"
66
#include "scheduler_queue.h"
7+
#include <ydb/library/actors/util/activation_queue.h>
78
#include <ydb/library/actors/util/affinity.h>
89
#include <ydb/library/actors/util/unordered_cache.h>
910
#include <ydb/library/actors/util/threadparkpad.h>
1011

12+
//#define RING_ACTIVATION_QUEUE
13+
1114
namespace NActors {
1215
class TActorSystem;
1316

@@ -43,10 +46,17 @@ namespace NActors {
4346

4447
class TExecutorPoolBase: public TExecutorPoolBaseMailboxed {
4548
protected:
49+
50+
#ifdef RING_ACTIVATION_QUEUE
51+
using TActivationQueue = TRingActivationQueue;
52+
#else
53+
using TActivationQueue = TUnorderedCache<ui32, 512, 4>;
54+
#endif
55+
4656
const i16 PoolThreads;
4757
TIntrusivePtr<TAffinity> ThreadsAffinity;
4858
TAtomic Semaphore = 0;
49-
TUnorderedCache<ui32, 512, 4> Activations;
59+
TActivationQueue Activations;
5060
TAtomic ActivationsRevolvingCounter = 0;
5161
std::atomic_bool StopFlag = false;
5262
public:

ydb/library/actors/core/thread_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "defs.h"
44

55
#include <ydb/library/actors/util/datetime.h>
6+
#include <ydb/library/actors/util/mpmc_ring_queue.h>
67

78
#include <util/system/tls.h>
89

@@ -42,6 +43,7 @@ namespace NActors {
4243
TWaitingStats<ui64> *WaitingStats = nullptr;
4344
bool IsCurrentRecipientAService = false;
4445
TTimers Timers;
46+
TMPMCRingQueue<20>::EPopMode ActivationPopMode = TMPMCRingQueue<20>::EPopMode::ReallySlow;
4547
};
4648

4749
extern Y_POD_THREAD(TThreadContext*) TlsThreadContext; // in actor.cpp
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#pragma once
2+
3+
#include "defs.h"
4+
#include "mpmc_ring_queue.h"
5+
#include <atomic>
6+
7+
8+
namespace NActors {
9+
10+
11+
class TRingActivationQueue {
12+
NThreading::TPadded<std::atomic_bool> IsNeedToWriteToOldQueue = false;
13+
NThreading::TPadded<TMPMCRingQueue<20>> ActivationQueue;
14+
NThreading::TPadded<TUnorderedCache<ui32, 512, 4>> OldActivationQueue;
15+
NThreading::TPadded<std::atomic_uint64_t> RevolvingCounter = 0;
16+
const bool IsMPSC = false;
17+
18+
public:
19+
TRingActivationQueue(bool isMPSC)
20+
: IsMPSC(isMPSC)
21+
{}
22+
23+
24+
void Push(ui32 activation, ui64 revolvingCounter) {
25+
if (!IsNeedToWriteToOldQueue.load(std::memory_order_acquire)) {
26+
if (ActivationQueue.TryPush(activation)) {
27+
return;
28+
}
29+
IsNeedToWriteToOldQueue.store(true, std::memory_order_release);
30+
}
31+
if (!revolvingCounter) {
32+
revolvingCounter = RevolvingCounter.fetch_add(1, std::memory_order_relaxed);
33+
}
34+
OldActivationQueue.Push(activation, AtomicIncrement(revolvingCounter));
35+
}
36+
37+
ui32 Pop(ui64 revolvingCounter) {
38+
std::optional<ui32> activation;
39+
if (IsMPSC) {
40+
activation = ActivationQueue.TryPopSingleConsumer();
41+
} else {
42+
activation = ActivationQueue.TryPop(TlsThreadContext->ActivationPopMode);
43+
}
44+
if (activation) {
45+
return *activation;
46+
}
47+
if (IsNeedToWriteToOldQueue.load(std::memory_order_acquire)) {
48+
return OldActivationQueue.Pop(revolvingCounter);
49+
}
50+
return 0;
51+
}
52+
53+
};
54+
55+
} // NActors

0 commit comments

Comments
 (0)