Skip to content

Commit 34c1476

Browse files
authored
KIKIMR-20042 Added table with statistics to LoadActor html report (#565)
1 parent ad749a9 commit 34c1476

File tree

1 file changed

+107
-37
lines changed

1 file changed

+107
-37
lines changed

ydb/core/load_test/keyvalue_write.cpp

Lines changed: 107 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <ydb/core/control/immediate_control_board_impl.h>
88
#include <ydb/core/keyvalue/keyvalue_events.h>
99

10+
#include <library/cpp/histogram/hdr/histogram.h>
1011
#include <library/cpp/monlib/service/pages/templates.h>
1112
#include <library/cpp/time_provider/time_provider.h>
1213

@@ -17,12 +18,6 @@
1718
namespace NKikimr {
1819
class TKeyValueWriterLoadTestActor;
1920

20-
#define PARAM(NAME, VALUE) \
21-
TABLER() { \
22-
TABLED() { str << NAME; } \
23-
TABLED() { str << VALUE; } \
24-
}
25-
2621
class TWorker {
2722
friend class TKeyValueWriterLoadTestActor;
2823

@@ -39,6 +34,10 @@ class TWorker {
3934
TString DataBuffer;
4035
TReallyFastRng32 *Gen;
4136
bool IsDying = false;
37+
38+
ui64 Errors = 0;
39+
ui64 OutOfBoundsLatencies = 0;
40+
NHdr::THistogram LatencyHistogram{6'000'000, 4};
4241
public:
4342

4443
TWorker(const NKikimr::TEvLoadTestRequest::TKeyValueLoad::TWorkerConfig& cmd,
@@ -87,12 +86,23 @@ class TWorker {
8786
return ev;
8887
}
8988

90-
void OnResult(ui32 size) {
91-
--ItemsInFlight;
92-
BytesInFlight -= size;
89+
void OnSuccess(ui32 size, TDuration responseTime) {
90+
ReduceInFlight(size);
91+
if (!LatencyHistogram.RecordValue(responseTime.MicroSeconds())) {
92+
LOG_INFO_S(*NActors::TActivationContext::ActorSystem(), NKikimrServices::BS_LOAD_TEST, "Worker# " << Idx << " skipped recording of " << responseTime << " response time");
93+
++OutOfBoundsLatencies;
94+
}
9395
}
9496

95-
~TWorker() {
97+
void OnFailure(ui32 size) {
98+
ReduceInFlight(size);
99+
++Errors;
100+
}
101+
102+
private:
103+
void ReduceInFlight(ui32 size) {
104+
--ItemsInFlight;
105+
BytesInFlight -= size;
96106
}
97107
};
98108

@@ -123,6 +133,7 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
123133
ui64 ReqIdx = 0;
124134
ui32 DurationSeconds;
125135
i32 OwnerInitInProgress = 0;
136+
TString ConfigString;
126137

127138
TReallyFastRng32 Rng;
128139

@@ -170,6 +181,8 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
170181
GetSubgroup("tablet", Sprintf("%09" PRIu64, TabletId));
171182
KeyValueBytesWritten = LoadCounters->GetCounter("KeyValueBytesWritten", true);
172183
ResponseTimes.Initialize(LoadCounters, "subsystem", "LoadActorLogWriteDuration", "Time in microseconds", percentiles);
184+
185+
google::protobuf::TextFormat::PrintToString(cmd, &ConfigString);
173186
}
174187

175188
~TKeyValueWriterLoadTestActor() {
@@ -198,9 +211,9 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
198211
for (auto& worker : Workers) {
199212
AppData(ctx)->Icb->RegisterLocalControl(worker->MaxInFlight,
200213
Sprintf("KeyValueWriteLoadActor_MaxInFlight_%04" PRIu64 "_%04" PRIu32, Tag, worker->Idx));
201-
LOG_INFO_S(ctx, NKikimrServices::BS_LOAD_TEST, "Tag# " << Tag << " last TEvKeyValueResult, "
202-
<< " all workers is initialized, start test");
203214
}
215+
LOG_INFO_S(ctx, NKikimrServices::BS_LOAD_TEST, "Tag# " << Tag << " last TEvKeyValueResult, "
216+
<< "all workers are initialized, start test");
204217
EarlyStop = false;
205218
Connect(ctx);
206219
}
@@ -232,7 +245,10 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
232245
}
233246
const TString errorReason = EarlyStop ?
234247
"Abort, stop signal received" : "OK, called StartDeathProcess";
235-
ctx.Send(Parent, new TEvLoad::TEvLoadTestFinished(Tag, report, errorReason));
248+
auto* finishEv = new TEvLoad::TEvLoadTestFinished(Tag, report, errorReason);
249+
finishEv->LastHtmlPage = RenderHTML(false);
250+
251+
ctx.Send(Parent, finishEv);
236252
NTabletPipe::CloseClient(SelfId(), Pipe);
237253
Die(ctx);
238254
}
@@ -258,8 +274,8 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
258274
void SendWriteRequests(const TActorContext& ctx) {
259275
ui64 sent = 0;
260276
for (auto& worker : Workers) {
261-
auto now = TAppData::TimeProvider->Now();
262277
while (std::unique_ptr<TEvKeyValue::TEvRequest> ev = worker->TrySend()) {
278+
auto now = TAppData::TimeProvider->Now();
263279
ui64 size = ev->Record.GetCmdWrite(0).GetValue().size();
264280
*KeyValueBytesWritten += size;
265281
ev->Record.SetCookie(ReqIdx);
@@ -275,24 +291,21 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
275291
void Handle(TEvKeyValue::TEvResponse::TPtr& ev, const TActorContext& ctx) {
276292
auto msg = ev->Get();
277293
auto record = msg->Record;
278-
if (record.GetStatus() != NMsgBusProxy::MSTATUS_OK) {
279-
TStringStream str;
280-
str << " TEvKeyValue::TEvResponse is not OK, msg.ToString()# " << msg->ToString();
281-
LOG_ERROR_S(ctx, NKikimrServices::BS_LOAD_TEST, str.Str());
282-
ctx.Send(Parent, new TEvLoad::TEvLoadTestFinished(Tag, nullptr, str.Str()));
283-
NTabletPipe::CloseClient(SelfId(), Pipe);
284-
Die(ctx);
285-
return;
286-
}
287294

288-
auto now = TAppData::TimeProvider->Now();
289295
auto it = InFlightWrites.find(record.GetCookie());
290296
Y_ABORT_UNLESS(it != InFlightWrites.end());
291297
const auto& stats = it->second;
292-
ResponseTimes.Increment((now - stats.SentTime).MicroSeconds());
298+
auto responseTime = TAppData::TimeProvider->Now() - stats.SentTime;
299+
ResponseTimes.Increment(responseTime.MicroSeconds());
293300
auto& worker = Workers[stats.WorkerIdx];
294301

295-
worker->OnResult(stats.Size);
302+
if (record.GetStatus() == NMsgBusProxy::MSTATUS_OK) {
303+
worker->OnSuccess(stats.Size, responseTime);
304+
} else {
305+
LOG_WARN_S(ctx, NKikimrServices::BS_LOAD_TEST, " TEvKeyValue::TEvResponse is not OK, msg.ToString()# " << msg->ToString());
306+
307+
worker->OnFailure(stats.Size);
308+
}
296309
WrittenBytes = WrittenBytes + stats.Size;
297310
LOG_TRACE_S(ctx, NKikimrServices::BS_LOAD_TEST, "Tag# " << Tag << " EvResult, "
298311
<< " WrittenBytes# " << WrittenBytes);
@@ -301,29 +314,86 @@ class TKeyValueWriterLoadTestActor : public TActorBootstrapped<TKeyValueWriterLo
301314
SendWriteRequests(ctx);
302315
}
303316

304-
void Handle(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx) {
317+
TString RenderHTML(bool showPassedTime) {
305318
TStringStream str;
306319
HTML(str) {
307-
TABLE() {
320+
if (showPassedTime) {
321+
PARA() {
322+
str << "Time passed: " << (TAppData::TimeProvider->Now() - TestStartTime).Seconds() << "s / "
323+
<< DurationSeconds << "s";
324+
}
325+
}
326+
TABLE_CLASS("table table-condenced") {
308327
TABLEHEAD() {
309328
TABLER() {
310-
TABLEH() { str << "Parameter"; }
311-
TABLEH() { str << "Value"; }
329+
TABLEH() {
330+
str << "Worker#";
331+
}
332+
TABLEH() {
333+
str << "Writes";
334+
}
335+
TABLEH() {
336+
str << "Errors";
337+
}
338+
TABLEH() {
339+
str << "OOB Latencies";
340+
}
341+
TABLEH() {
342+
str << "p50(ms)";
343+
}
344+
TABLEH() {
345+
str << "p95(ms)";
346+
}
347+
TABLEH() {
348+
str << "p99(ms)";
349+
}
350+
TABLEH() {
351+
str << "pMax(ms)";
352+
}
312353
}
313354
}
314355
TABLEBODY() {
315-
316-
PARAM("Elapsed time / Duration", (TAppData::TimeProvider->Now() - TestStartTime).Seconds() << "s / "
317-
<< DurationSeconds << "s");
318-
for (auto& worker : Workers) {
319-
PARAM("Worker idx", worker->Idx);
320-
PARAM("Worker next OperationIdx", worker->OperationIdx);
356+
for (auto& worker: Workers) {
357+
TABLER() {
358+
TABLED() {
359+
str << worker->Idx;
360+
}
361+
TABLED() {
362+
str << worker->LatencyHistogram.GetTotalCount();
363+
}
364+
TABLED() {
365+
str << worker->Errors;
366+
}
367+
TABLED() {
368+
str << worker->OutOfBoundsLatencies;
369+
}
370+
TABLED() {
371+
str << worker->LatencyHistogram.GetValueAtPercentile(50.0) / 1000.0;
372+
}
373+
TABLED() {
374+
str << worker->LatencyHistogram.GetValueAtPercentile(95.0) / 1000.0;
375+
}
376+
TABLED() {
377+
str << worker->LatencyHistogram.GetValueAtPercentile(99.0) / 1000.0;
378+
}
379+
TABLED() {
380+
str << worker->LatencyHistogram.GetMax() / 1000.0;
381+
}
382+
}
321383
}
322384
}
323385
}
386+
COLLAPSED_BUTTON_CONTENT(Sprintf("configProtobuf%" PRIu64, Tag), "Config") {
387+
PRE() {
388+
str << ConfigString;
389+
}
390+
}
324391
}
392+
return str.Str();
393+
}
325394

326-
ctx.Send(ev->Sender, new NMon::TEvHttpInfoRes(str.Str(), ev->Get()->SubRequestId));
395+
void Handle(NMon::TEvHttpInfo::TPtr& ev, const TActorContext& ctx) {
396+
ctx.Send(ev->Sender, new NMon::TEvHttpInfoRes(RenderHTML(true), ev->Get()->SubRequestId));
327397
}
328398

329399
void Handle(TEvTabletPipe::TEvClientConnected::TPtr ev, const TActorContext& ctx) {

0 commit comments

Comments
 (0)