Skip to content

Commit ca63e12

Browse files
authored
Perf[MQB]: less allocations for ElectorEvent (#986)
Signed-off-by: Evgeny Malygin <[email protected]>
1 parent eef016a commit ca63e12

File tree

4 files changed

+72
-21
lines changed

4 files changed

+72
-21
lines changed

src/groups/bmq/bmqp/bmqp_protocolutil.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,11 @@ int ProtocolUtil::encodeMessage(bsl::ostream& errorDescription,
524524
balber::BerEncoderOptions options;
525525
balber::BerEncoder encoder(&options, allocator);
526526

527-
int rc = encoder.encode(out, message);
527+
const int rc = encoder.encode(out, message);
528528

529529
// Debug print message if any
530530
bslstl::StringRef logStr = encoder.loggedMessages();
531-
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(logStr.length() != 0)) {
531+
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!logStr.empty())) {
532532
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
533533
errorDescription << "BER encoder returned the following "
534534
<< "[rc: " << rc << "]\n"
@@ -541,11 +541,11 @@ int ProtocolUtil::encodeMessage(bsl::ostream& errorDescription,
541541
baljsn::EncoderOptions options;
542542
baljsn::Encoder encoder(allocator);
543543

544-
int rc = encoder.encode(out, message, options);
544+
const int rc = encoder.encode(out, message, options);
545545

546546
// Debug print message if any
547547
bsl::string logStr = encoder.loggedMessages();
548-
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(logStr.length() != 0)) {
548+
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!logStr.empty())) {
549549
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
550550
errorDescription << "JSON encoder returned the following "
551551
<< "[rc: " << rc << "]\n"
@@ -593,15 +593,15 @@ int ProtocolUtil::decodeMessage(bsl::ostream& errorDescription,
593593
switch (encodingType) {
594594
case EncodingType::e_BER: {
595595
balber::BerDecoderOptions options;
596-
balber::BerDecoder decoder(&options, allocator);
597596
options.setSkipUnknownElements(true);
598597
options.setDefaultEmptyStrings(false);
598+
balber::BerDecoder decoder(&options, allocator);
599599

600-
int rc = decoder.decode(stream, message);
600+
const int rc = decoder.decode(stream, message);
601601

602602
// Debug print message if any
603603
bslstl::StringRef logStr = decoder.loggedMessages();
604-
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(logStr.length() != 0)) {
604+
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!logStr.empty())) {
605605
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
606606
errorDescription << "BER decoder returned the following "
607607
<< "[rc: " << rc << "]\n"
@@ -615,11 +615,11 @@ int ProtocolUtil::decodeMessage(bsl::ostream& errorDescription,
615615
baljsn::DecoderOptions options;
616616
options.setSkipUnknownElements(true);
617617

618-
int rc = decoder.decode(stream, message, options);
618+
const int rc = decoder.decode(stream, message, options);
619619

620620
// Debug print message if any
621621
bsl::string logStr = decoder.loggedMessages();
622-
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(logStr.length() != 0)) {
622+
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!logStr.empty())) {
623623
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
624624
errorDescription << "JSON decoder returned the following "
625625
<< "[rc: " << rc << "]\n"

src/groups/mqb/mqbblp/mqbblp_clusterorchestrator.cpp

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,33 @@ const bsls::Types::Int64 k_WATCHDOG_TIMEOUT_DURATION = 60 * 5;
6262

6363
} // close unnamed namespace
6464

65+
// ------------------------------------------------
66+
// class ClusterOrchestrator::OnElectorEventFunctor
67+
// ------------------------------------------------
68+
69+
ClusterOrchestrator::OnElectorEventFunctor::OnElectorEventFunctor(
70+
ClusterOrchestrator* orchestrator_p,
71+
bslmf::MovableRef<bmqp::Event> event,
72+
mqbnet::ClusterNode* source_p)
73+
: d_orchestrator_p(orchestrator_p)
74+
, d_event(bslmf::MovableRefUtil::move(event))
75+
, d_source_p(source_p)
76+
{
77+
// PRECONDITIONS
78+
BSLS_ASSERT_SAFE(d_orchestrator_p);
79+
}
80+
81+
ClusterOrchestrator::OnElectorEventFunctor::~OnElectorEventFunctor()
82+
{
83+
// NOTHING
84+
}
85+
86+
void ClusterOrchestrator::OnElectorEventFunctor::operator()() const
87+
{
88+
// Thread: CLUSTER dispatcher
89+
d_orchestrator_p->processElectorEventDispatched(d_event, d_source_p);
90+
}
91+
6592
// -------------------------
6693
// class ClusterOrchestrator
6794
// -------------------------
@@ -665,7 +692,7 @@ int ClusterOrchestrator::start(bsl::ostream& errorDescription)
665692
_4), // Term
666693
ledgerLSN.electorTerm(),
667694
&d_clusterData_p->blobSpPool(),
668-
d_allocator_p),
695+
d_allocators.get("Elector")),
669696
d_allocator_p);
670697

671698
rc = d_elector_mp->start();
@@ -1241,17 +1268,19 @@ void ClusterOrchestrator::processElectorEvent(const bmqp::Event& event,
12411268
// important that elector events are processed in the dispatcher thread
12421269
// too, otherwise, depending upon thread scheduling, a new node may get
12431270
// certain events "out of order" (some cases were found out while testing).
1244-
// Note that 'bindA' instead of 'bind' is needed below because we need to
1245-
// pass allocator to one of the 'bmqp::Event' instances created below
1246-
// (allocator is *not* optional for 'bmqp::Event')
1247-
dispatcher()->execute(
1248-
bdlf::BindUtil::bindS(
1249-
d_allocator_p,
1250-
&ClusterOrchestrator::processElectorEventDispatched,
1271+
1272+
mqbi::DispatcherEvent* clusterEvent = dispatcher()->getEvent(
1273+
mqbi::DispatcherClientType::e_CLUSTER);
1274+
1275+
(*clusterEvent).setType(mqbi::DispatcherEventType::e_CALLBACK);
1276+
1277+
clusterEvent->callback()
1278+
.createInplace<ClusterOrchestrator::OnElectorEventFunctor>(
12511279
this,
12521280
event.clone(d_allocator_p),
1253-
source),
1254-
d_cluster_p);
1281+
source);
1282+
1283+
dispatcher()->dispatchEvent(clusterEvent, d_cluster_p);
12551284
}
12561285

12571286
void ClusterOrchestrator::processLeaderSyncStateQuery(

src/groups/mqb/mqbblp/mqbblp_clusterorchestrator.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,27 @@ class ClusterOrchestrator {
112112

113113
typedef mqbc::ClusterStateQueueInfo::AppInfos AppInfos;
114114

115+
/// The purpose is to avoid memory allocation by bdlf::BindUtil::bind
116+
/// when dispatching ElectorEvent from IO to Cluster.
117+
class OnElectorEventFunctor
118+
: public bmqu::ManagedCallback::CallbackFunctor {
119+
private:
120+
// PRIVATE DATA
121+
ClusterOrchestrator* d_orchestrator_p;
122+
const bmqp::Event d_event;
123+
mqbnet::ClusterNode* d_source_p;
124+
125+
public:
126+
// CREATORS
127+
explicit OnElectorEventFunctor(ClusterOrchestrator* orchestrator,
128+
bslmf::MovableRef<bmqp::Event> event,
129+
mqbnet::ClusterNode* source_p);
130+
131+
~OnElectorEventFunctor() BSLS_KEYWORD_OVERRIDE;
132+
133+
void operator()() const BSLS_KEYWORD_OVERRIDE;
134+
};
135+
115136
private:
116137
// DATA
117138

src/groups/mqb/mqbnet/mqbnet_elector.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,9 +2079,10 @@ void Elector::emitIOEvent(const ElectorStateMachineOutput& output)
20792079
// 'emitIOEvent' is currently always called while 'd_lock' is held, but
20802080
// that's an implementation side effect, not part of contract. That's why
20812081
// we create the builder on stack instead of making it a class member.
2082-
bmqp::SchemaEventBuilder builder(d_blobSpPool_p,
2082+
bdlma::LocalSequentialAllocator<256> localAllocator(d_allocator_p);
2083+
bmqp::SchemaEventBuilder builder(d_blobSpPool_p,
20832084
bmqp::EncodingType::e_BER,
2084-
d_allocator_p);
2085+
&localAllocator);
20852086

20862087
int rc = builder.setMessage(message, bmqp::EventType::e_ELECTOR);
20872088
if (0 != rc) {

0 commit comments

Comments
 (0)