@@ -6,7 +6,8 @@ BedrockCommand::BedrockCommand() :
6
6
httpsRequest(nullptr ),
7
7
priority(PRIORITY_NORMAL),
8
8
peekCount(0 ),
9
- processCount(0 )
9
+ processCount(0 ),
10
+ _inProgressTiming(INVALID, 0 , 0 )
10
11
{ }
11
12
12
13
BedrockCommand::~BedrockCommand () {
@@ -21,7 +22,8 @@ BedrockCommand::BedrockCommand(SQLiteCommand&& from) :
21
22
httpsRequest(nullptr ),
22
23
priority(PRIORITY_NORMAL),
23
24
peekCount(0 ),
24
- processCount(0 )
25
+ processCount(0 ),
26
+ _inProgressTiming(INVALID, 0 , 0 )
25
27
{
26
28
_init ();
27
29
}
@@ -32,7 +34,8 @@ BedrockCommand::BedrockCommand(BedrockCommand&& from) :
32
34
priority(from.priority),
33
35
peekCount(from.peekCount),
34
36
processCount(from.processCount),
35
- timingInfo(from.timingInfo)
37
+ timingInfo(from.timingInfo),
38
+ _inProgressTiming(from._inProgressTiming)
36
39
{
37
40
// The move constructor (and likewise, the move assignment operator), don't simply copy this pointer value, but
38
41
// 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) :
44
47
httpsRequest(nullptr ),
45
48
priority(PRIORITY_NORMAL),
46
49
peekCount(0 ),
47
- processCount(0 )
50
+ processCount(0 ),
51
+ _inProgressTiming(INVALID, 0 , 0 )
48
52
{
49
53
_init ();
50
54
}
@@ -54,7 +58,8 @@ BedrockCommand::BedrockCommand(SData _request) :
54
58
httpsRequest(nullptr ),
55
59
priority(PRIORITY_NORMAL),
56
60
peekCount(0 ),
57
- processCount(0 )
61
+ processCount(0 ),
62
+ _inProgressTiming(INVALID, 0 , 0 )
58
63
{
59
64
_init ();
60
65
}
@@ -74,6 +79,7 @@ BedrockCommand& BedrockCommand::operator=(BedrockCommand&& from) {
74
79
processCount = from.processCount ;
75
80
priority = from.priority ;
76
81
timingInfo = from.timingInfo ;
82
+ _inProgressTiming = from._inProgressTiming ;
77
83
78
84
// And call the base class's move constructor as well.
79
85
SQLiteCommand::operator =(move (from));
@@ -104,22 +110,81 @@ void BedrockCommand::_init() {
104
110
}
105
111
}
106
112
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
+
107
141
void BedrockCommand::finalizeTimingInfo () {
108
142
uint64_t peekTotal = 0 ;
109
143
uint64_t processTotal = 0 ;
144
+ uint64_t commitWorkerTotal = 0 ;
145
+ uint64_t commitSyncTotal = 0 ;
146
+ uint64_t queueWorkerTotal = 0 ;
147
+ uint64_t queueSyncTotal = 0 ;
110
148
for (const auto & entry: timingInfo) {
111
149
if (get<0 >(entry) == PEEK) {
112
150
peekTotal += get<2 >(entry) - get<1 >(entry);
113
151
} else if (get<0 >(entry) == PROCESS) {
114
152
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);
115
161
}
116
162
}
117
163
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
+
118
183
// Build a map of the values we care about.
119
184
map<string, uint64_t > valuePairs = {
120
185
{" peekTime" , peekTotal},
121
186
{" processTime" , processTotal},
122
- {" totalTime" , STimeNow () - creationTime },
187
+ {" totalTime" , totalTime },
123
188
{" escalationTime" , escalationTimeUS},
124
189
};
125
190
@@ -142,3 +207,28 @@ void BedrockCommand::finalizeTimingInfo() {
142
207
}
143
208
}
144
209
}
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
+ }
0 commit comments