Skip to content

Commit e7bb200

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 63a05f8 + 1758e8a commit e7bb200

17 files changed

+245
-100
lines changed

BedrockCommand.cpp

+96-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ BedrockCommand::BedrockCommand() :
66
httpsRequest(nullptr),
77
priority(PRIORITY_NORMAL),
88
peekCount(0),
9-
processCount(0)
9+
processCount(0),
10+
_inProgressTiming(INVALID, 0, 0)
1011
{ }
1112

1213
BedrockCommand::~BedrockCommand() {
@@ -21,7 +22,8 @@ BedrockCommand::BedrockCommand(SQLiteCommand&& from) :
2122
httpsRequest(nullptr),
2223
priority(PRIORITY_NORMAL),
2324
peekCount(0),
24-
processCount(0)
25+
processCount(0),
26+
_inProgressTiming(INVALID, 0, 0)
2527
{
2628
_init();
2729
}
@@ -32,7 +34,8 @@ BedrockCommand::BedrockCommand(BedrockCommand&& from) :
3234
priority(from.priority),
3335
peekCount(from.peekCount),
3436
processCount(from.processCount),
35-
timingInfo(from.timingInfo)
37+
timingInfo(from.timingInfo),
38+
_inProgressTiming(from._inProgressTiming)
3639
{
3740
// The move constructor (and likewise, the move assignment operator), don't simply copy this pointer value, but
3841
// they clear it from the old object, so that when its destructor is called, the HTTPS transaction isn't closed.
@@ -44,7 +47,8 @@ BedrockCommand::BedrockCommand(SData&& _request) :
4447
httpsRequest(nullptr),
4548
priority(PRIORITY_NORMAL),
4649
peekCount(0),
47-
processCount(0)
50+
processCount(0),
51+
_inProgressTiming(INVALID, 0, 0)
4852
{
4953
_init();
5054
}
@@ -54,7 +58,8 @@ BedrockCommand::BedrockCommand(SData _request) :
5458
httpsRequest(nullptr),
5559
priority(PRIORITY_NORMAL),
5660
peekCount(0),
57-
processCount(0)
61+
processCount(0),
62+
_inProgressTiming(INVALID, 0, 0)
5863
{
5964
_init();
6065
}
@@ -74,6 +79,7 @@ BedrockCommand& BedrockCommand::operator=(BedrockCommand&& from) {
7479
processCount = from.processCount;
7580
priority = from.priority;
7681
timingInfo = from.timingInfo;
82+
_inProgressTiming = from._inProgressTiming;
7783

7884
// And call the base class's move constructor as well.
7985
SQLiteCommand::operator=(move(from));
@@ -104,22 +110,81 @@ void BedrockCommand::_init() {
104110
}
105111
}
106112

113+
void BedrockCommand::startTiming(TIMING_INFO type) {
114+
if (get<0>(_inProgressTiming) != INVALID ||
115+
get<1>(_inProgressTiming) != 0
116+
) {
117+
SWARN("Starting timing, but looks like it was already running.");
118+
}
119+
get<0>(_inProgressTiming) = type;
120+
get<1>(_inProgressTiming) = STimeNow();
121+
get<2>(_inProgressTiming) = 0;
122+
}
123+
124+
void BedrockCommand::stopTiming(TIMING_INFO type) {
125+
if (get<0>(_inProgressTiming) != type ||
126+
get<1>(_inProgressTiming) == 0
127+
) {
128+
SWARN("Stopping timing, but looks like it wasn't already running.");
129+
}
130+
131+
// Add it to the list of timing info.
132+
get<2>(_inProgressTiming) = STimeNow();
133+
timingInfo.push_back(_inProgressTiming);
134+
135+
// And reset it for next use.
136+
get<0>(_inProgressTiming) = INVALID;
137+
get<1>(_inProgressTiming) = 0;
138+
get<2>(_inProgressTiming) = 0;
139+
}
140+
107141
void BedrockCommand::finalizeTimingInfo() {
108142
uint64_t peekTotal = 0;
109143
uint64_t processTotal = 0;
144+
uint64_t commitWorkerTotal = 0;
145+
uint64_t commitSyncTotal = 0;
146+
uint64_t queueWorkerTotal = 0;
147+
uint64_t queueSyncTotal = 0;
110148
for (const auto& entry: timingInfo) {
111149
if (get<0>(entry) == PEEK) {
112150
peekTotal += get<2>(entry) - get<1>(entry);
113151
} else if (get<0>(entry) == PROCESS) {
114152
processTotal += get<2>(entry) - get<1>(entry);
153+
} else if (get<0>(entry) == COMMIT_WORKER) {
154+
commitWorkerTotal += get<2>(entry) - get<1>(entry);
155+
} else if (get<0>(entry) == COMMIT_SYNC) {
156+
commitSyncTotal += get<2>(entry) - get<1>(entry);
157+
} else if (get<0>(entry) == QUEUE_WORKER) {
158+
queueWorkerTotal += get<2>(entry) - get<1>(entry);
159+
} else if (get<0>(entry) == QUEUE_SYNC) {
160+
queueSyncTotal += get<2>(entry) - get<1>(entry);
115161
}
116162
}
117163

164+
// The lifespan of the object up until now.
165+
uint64_t totalTime = STimeNow() - creationTime;
166+
167+
// Time that wasn't accounted for in all the other metrics.
168+
uint64_t unaccountedTime = totalTime - (peekTotal + processTotal + commitWorkerTotal + commitSyncTotal +
169+
queueWorkerTotal + queueSyncTotal);
170+
171+
// Log all this info.
172+
SINFO("command '" << request.methodLine << "' timing info (us): "
173+
<< peekTotal << " (" << peekCount << "), "
174+
<< processTotal << " (" << processCount << "), "
175+
<< commitWorkerTotal << ", "
176+
<< commitSyncTotal << ", "
177+
<< queueWorkerTotal << ", "
178+
<< queueSyncTotal << ", "
179+
<< totalTime << ", "
180+
<< unaccountedTime << "."
181+
);
182+
118183
// Build a map of the values we care about.
119184
map<string, uint64_t> valuePairs = {
120185
{"peekTime", peekTotal},
121186
{"processTime", processTotal},
122-
{"totalTime", STimeNow() - creationTime},
187+
{"totalTime", totalTime},
123188
{"escalationTime", escalationTimeUS},
124189
};
125190

@@ -142,3 +207,28 @@ void BedrockCommand::finalizeTimingInfo() {
142207
}
143208
}
144209
}
210+
211+
// pop and push specializations for SSynchronizedQueue that record timing info.
212+
template<>
213+
BedrockCommand SSynchronizedQueue<BedrockCommand>::pop() {
214+
SAUTOLOCK(_queueMutex);
215+
if (!_queue.empty()) {
216+
BedrockCommand item = move(_queue.front());
217+
_queue.pop_front();
218+
item.stopTiming(BedrockCommand::QUEUE_SYNC);
219+
return item;
220+
}
221+
throw out_of_range("No commands");
222+
}
223+
224+
template<>
225+
void SSynchronizedQueue<BedrockCommand>::push(BedrockCommand&& rhs) {
226+
SAUTOLOCK(_queueMutex);
227+
// Just add to the queue
228+
_queue.push_back(move(rhs));
229+
_queue.back().startTiming(BedrockCommand::QUEUE_SYNC);
230+
231+
// Write arbitrary buffer to the pipe so any subscribers will be awoken.
232+
// **NOTE: 1 byte so write is atomic.
233+
SASSERT(write(_pipeFD[1], "A", 1));
234+
}

BedrockCommand.h

+15
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ class BedrockCommand : public SQLiteCommand {
1212
};
1313

1414
enum TIMING_INFO {
15+
INVALID,
1516
PEEK,
1617
PROCESS,
18+
COMMIT_WORKER,
19+
COMMIT_SYNC,
20+
QUEUE_WORKER,
21+
QUEUE_SYNC,
1722
};
1823

1924
// Constructor to make an empty object.
@@ -37,6 +42,13 @@ class BedrockCommand : public SQLiteCommand {
3742
// Move assignment operator.
3843
BedrockCommand& operator=(BedrockCommand&& from);
3944

45+
// Start recording time for a given action type.
46+
void startTiming(TIMING_INFO type);
47+
48+
// Finish recording time for a given action type. `type` must match what was passed to the most recent call to
49+
// `startTiming`.
50+
void stopTiming(TIMING_INFO type);
51+
4052
// Add a summary of our timing info to our response object.
4153
void finalizeTimingInfo();
4254

@@ -56,4 +68,7 @@ class BedrockCommand : public SQLiteCommand {
5668
private:
5769
// Set certain initial state on construction. Common functionality to several constructors.
5870
void _init();
71+
72+
// used as a temporary variable for startTiming and stopTiming.
73+
tuple<TIMING_INFO, uint64_t, uint64_t> _inProgressTiming;
5974
};

BedrockCommandQueue.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ list<string> BedrockCommandQueue::getRequestMethodLines() {
8888
void BedrockCommandQueue::push(BedrockCommand&& item) {
8989
SAUTOLOCK(_queueMutex);
9090
auto& queue = _commandQueue[item.priority];
91+
item.startTiming(BedrockCommand::QUEUE_WORKER);
9192
queue.emplace(item.request.calcU64("commandExecuteTime"), move(item));
9293
_queueCondition.notify_one();
9394
}
@@ -136,6 +137,7 @@ BedrockCommand BedrockCommandQueue::_dequeue() {
136137
}
137138

138139
// Done!
140+
command.stopTiming(BedrockCommand::QUEUE_WORKER);
139141
return command;
140142
}
141143
}

BedrockCore.h

+14-14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ class BedrockCore : public SQLiteCore {
77
public:
88
BedrockCore(SQLite& db, const BedrockServer& server);
99

10+
// Automatic timing class that records an entry corresponding to its lifespan.
11+
class AutoTimer {
12+
public:
13+
AutoTimer(BedrockCommand& command, BedrockCommand::TIMING_INFO type) :
14+
_command(command), _type(type), _start(STimeNow()) { }
15+
~AutoTimer() {
16+
_command.timingInfo.emplace_back(make_tuple(_type, _start, STimeNow()));
17+
}
18+
private:
19+
BedrockCommand& _command;
20+
BedrockCommand::TIMING_INFO _type;
21+
uint64_t _start;
22+
};
23+
1024
// Peek lets you pre-process a command. It will be called on each command before `process` is called on the same
1125
// command, and it *may be called multiple times*. Preventing duplicate actions on calling peek multiple times is
1226
// up to the implementer, and may happen *across multiple servers*. I.e., a slave server may call `peek`, and on
@@ -29,20 +43,6 @@ class BedrockCore : public SQLiteCore {
2943
bool processCommand(BedrockCommand& command);
3044

3145
private:
32-
33-
// Automatic timing class that records an entry corresponding to its lifespan.
34-
class AutoTimer {
35-
public:
36-
AutoTimer(BedrockCommand& command, BedrockCommand::TIMING_INFO type) :
37-
_command(command), _type(type), _start(STimeNow()) { }
38-
~AutoTimer() {
39-
_command.timingInfo.emplace_back(make_tuple(_type, _start, STimeNow()));
40-
}
41-
private:
42-
BedrockCommand& _command;
43-
BedrockCommand::TIMING_INFO _type;
44-
uint64_t _start;
45-
};
4646
void _handleCommandException(BedrockCommand& command, const string& e, bool wasProcessing);
4747
const BedrockServer& _server;
4848
};

BedrockServer.cpp

+12-1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ void BedrockServer::sync(SData& args,
210210
// It should be impossible to get here if we're not mastering or standing down.
211211
SASSERT(nodeState == SQLiteNode::MASTERING || nodeState == SQLiteNode::STANDINGDOWN);
212212

213+
// Record the time spent.
214+
command.stopTiming(BedrockCommand::COMMIT_SYNC);
215+
213216
// We're done with the commit, we unlock our mutex and decrement our counter.
214217
server._syncThreadCommitMutex.unlock();
215218
committingCommand = false;
@@ -324,6 +327,8 @@ void BedrockServer::sync(SData& args,
324327
committingCommand = true;
325328
SINFO("[performance] Sync thread beginning committing command " << command.request.methodLine);
326329
server._writableCommandsInProgress++;
330+
// START TIMING.
331+
command.startTiming(BedrockCommand::COMMIT_SYNC);
327332
syncNode.startCommit(command.writeConsistency);
328333

329334
// And we'll start the next main loop.
@@ -566,7 +571,13 @@ void BedrockServer::worker(SData& args,
566571
<< " during worker commit. Rolling back transaction!");
567572
core.rollback();
568573
} else {
569-
if (core.commit()) {
574+
bool commitSuccess;
575+
{
576+
// Scoped for auto-timer.
577+
BedrockCore::AutoTimer(command, BedrockCommand::COMMIT_WORKER);
578+
commitSuccess = core.commit();
579+
}
580+
if (commitSuccess) {
570581
BedrockConflictMetrics::recordSuccess(command.request.methodLine);
571582
SINFO("Successfully committed " << command.request.methodLine << " on worker thread.");
572583
// So we must still be mastering, and at this point our commit has succeeded, let's

Makefile

-6
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,14 @@ STUFFC = $(shell find libstuff -name '*.c')
9494
STUFFOBJ = $(STUFFCPP:%.cpp=$(INTERMEDIATEDIR)/%.o) $(STUFFC:%.c=$(INTERMEDIATEDIR)/%.o)
9595
STUFFDEP = $(STUFFCPP:%.cpp=$(INTERMEDIATEDIR)/%.d)
9696

97-
$(info $$STUFFCPP is [${STUFFCPP}])
98-
9997
LIBBEDROCKCPP = $(shell find * -name '*.cpp' -not -name main.cpp -not -path 'test*' -not -path 'libstuff*')
10098
LIBBEDROCKOBJ = $(LIBBEDROCKCPP:%.cpp=$(INTERMEDIATEDIR)/%.o)
10199
LIBBEDROCKDEP = $(LIBBEDROCKCPP:%.cpp=$(INTERMEDIATEDIR)/%.d)
102100

103-
$(info $$LIBBEDROCKCPP is [${LIBBEDROCKCPP}])
104-
105101
BEDROCKCPP = main.cpp
106102
BEDROCKOBJ = $(BEDROCKCPP:%.cpp=$(INTERMEDIATEDIR)/%.o)
107103
BEDROCKDEP = $(BEDROCKCPP:%.cpp=$(INTERMEDIATEDIR)/%.d)
108104

109-
$(info $$BEDROCKCPP is [${BEDROCKCPP}])
110-
111105
TESTCPP = $(shell find test -name '*.cpp' -not -path 'test/clustertest*')
112106
TESTOBJ = $(TESTCPP:%.cpp=$(INTERMEDIATEDIR)/%.o)
113107
TESTDEP = $(TESTCPP:%.cpp=$(INTERMEDIATEDIR)/%.d)

libstuff/libstuff.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -815,11 +815,11 @@ struct STestTimer {
815815
#include "STCPServer.h"
816816
#include "STCPNode.h"
817817
#include "SHTTPSManager.h"
818-
#include "SSynchronizedQueue.h"
819818

820819
// Other libstuff headers.
821820
#include "SRandom.h"
822821
#include "SPerformanceTimer.h"
823822
#include "SLockTimer.h"
823+
#include "SSynchronizedQueue.h"
824824

825825
#endif // LIBSTUFF_H

0 commit comments

Comments
 (0)