41
41
#include " Basics/FileUtils.h"
42
42
#include " Basics/NumberOfCores.h"
43
43
#include " Basics/StaticStrings.h"
44
- #include " Basics/StringUtils.h"
45
44
#include " Basics/Utf8Helper.h"
46
45
#include " Basics/application-exit.h"
47
46
#include " Basics/files.h"
48
47
#include " Basics/system-functions.h"
49
48
#include " Benchmark/BenchmarkCounter.h"
50
49
#include " Benchmark/BenchmarkOperation.h"
51
50
#include " Benchmark/BenchmarkStats.h"
52
- #include " Benchmark/BenchmarkThread.h"
53
51
#include " FeaturePhases/BasicFeaturePhaseClient.h"
54
52
#include " Logger/LogMacros.h"
55
53
#include " Logger/Logger.h"
@@ -92,6 +90,7 @@ BenchFeature::BenchFeature(application_features::ApplicationServer& server, int*
92
90
_progress(true ),
93
91
_quiet(false ),
94
92
_waitForSync(false ),
93
+ _generateHistogram(false ),
95
94
_runs(1 ),
96
95
_junitReportFile(" " ),
97
96
_jsonReportFile(" " ),
@@ -144,6 +143,10 @@ void BenchFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
144
143
options->addOption (" --histogram.percentiles" , " which percentiles to calculate" ,
145
144
new VectorParameter<DoubleParameter>(&_percentiles),
146
145
arangodb::options::makeDefaultFlags (options::Flags::FlushOnFirst));
146
+ options->addOption (" --histogram.generate" , " display histogram" ,
147
+ new BooleanParameter (&_generateHistogram),
148
+ arangodb::options::makeDefaultFlags (options::Flags::FlushOnFirst))
149
+ .setIntroducedIn (31000 );
147
150
148
151
options->addOption (" --async" , " send asynchronous requests" , new BooleanParameter (&_async));
149
152
@@ -239,6 +242,26 @@ void BenchFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
239
242
" --verbose" , " print out replies if the HTTP header indicates DB errors" , false );
240
243
}
241
244
245
+ void BenchFeature::validateOptions (std::shared_ptr<ProgramOptions> options) {
246
+ if (!_generateHistogram) {
247
+ if (options->processingResult ().touched (" --histogram.interval-size" )) {
248
+ LOG_TOPIC (" 8b53b" , WARN, arangodb::Logger::BENCH)
249
+ << " For flag '--histogram.interval-size "
250
+ << _histogramIntervalSize << " ': histogram is disabled by default. Enable it with flag '--histogram.generate = true'." ;
251
+ }
252
+ if (options->processingResult ().touched (" --histogram.num-intervals" )) {
253
+ LOG_TOPIC (" 02916" , WARN, arangodb::Logger::BENCH)
254
+ << " For flag '--histogram.num-intervals "
255
+ << _histogramNumIntervals << " ': histogram is disabled by default. Enable it with flag '--histogram.generate = true'." ;
256
+ }
257
+ if (options->processingResult ().touched (" --histogram.percentiles" )) {
258
+ LOG_TOPIC (" ad47b" , WARN, arangodb::Logger::BENCH)
259
+ << " For flag '--histogram.percentiles "
260
+ << _percentiles << " ': histogram is disabled by default. Enable it with flag '--histogram.generate = true'." ;
261
+ }
262
+ }
263
+ }
264
+
242
265
void BenchFeature::status (std::string const & value) {
243
266
if (!_quiet) {
244
267
LOG_TOPIC (" a6905" , INFO, arangodb::Logger::BENCH) << value;
@@ -251,6 +274,49 @@ void BenchFeature::updateStartCounter() { ++_started; }
251
274
252
275
int BenchFeature::getStartCounter () { return _started; }
253
276
277
+ void BenchFeature::setupHistogram (std::stringstream& pp) {
278
+ pp << " Interval/Percentile:" ;
279
+ for (auto percentile : _percentiles) {
280
+ pp << std::fixed << std::right << std::setw (13 ) << std::setprecision (2 )
281
+ << percentile << " %" ;
282
+ }
283
+ pp << ' \n ' ;
284
+
285
+ }
286
+ void BenchFeature::updateStatsValues (std::stringstream& pp, VPackBuilder& builder,
287
+ const std::vector<std::unique_ptr<BenchmarkThread>>& threads,
288
+ BenchmarkStats& totalStats) {
289
+ for (size_t i = 0 ; i < static_cast <size_t >(_concurrency); ++i) {
290
+ if (_duration != 0 ) {
291
+ _realOperations += threads[i]->_counter ;
292
+ }
293
+
294
+ totalStats.add (threads[i]->stats ());
295
+ if (_generateHistogram) {
296
+ double scope;
297
+ auto res = threads[i]->getPercentiles (_percentiles, scope);
298
+
299
+ builder.add (std::to_string (i), VPackValue (VPackValueType::Object));
300
+ size_t j = 0 ;
301
+
302
+ pp << " " << std::right << std::fixed << std::setw (17 )
303
+ << std::setprecision (4 ) << (threads[i]->_histogramIntervalSize * 1000 )
304
+ << std::setw (0 ) << " ms" ;
305
+
306
+ builder.add (" IntervalSize" , VPackValue (threads[i]->_histogramIntervalSize ));
307
+
308
+ for (auto time : res) {
309
+ builder.add (std::to_string (_percentiles[j]), VPackValue (time ));
310
+ pp << " " << std::right << std::fixed << std::setw (9 )
311
+ << std::setprecision (4 ) << (time * 1000 ) << std::setw (0 ) << " ms" ;
312
+ j++;
313
+ }
314
+ pp << ' \n ' ;
315
+ builder.close ();
316
+ }
317
+ }
318
+ }
319
+
254
320
void BenchFeature::start () {
255
321
std::sort (_percentiles.begin (), _percentiles.end ());
256
322
@@ -289,6 +355,7 @@ void BenchFeature::start() {
289
355
290
356
client.setDatabaseName (connectDB);
291
357
}
358
+
292
359
int ret = EXIT_SUCCESS;
293
360
294
361
*_result = ret;
@@ -333,19 +400,16 @@ void BenchFeature::start() {
333
400
// aggregated stats for all runs
334
401
BenchmarkStats totalStats;
335
402
336
- auto builder = std::make_shared<VPackBuilder>();
337
- builder->openObject ();
338
- builder->add (" histogram" , VPackValue (VPackValueType::Object));
403
+ VPackBuilder builder;
404
+ builder.openObject ();
339
405
std::vector<std::unique_ptr<BenchmarkThread>> threads;
340
406
bool ok = true ;
341
407
std::vector<BenchRunResult> results;
342
408
std::stringstream pp;
343
- pp << " Interval/Percentile:" ;
344
- for (auto percentile : _percentiles) {
345
- pp << std::fixed << std::right << std::setw (12 ) << std::setprecision (2 )
346
- << percentile << " %" ;
409
+ if (_generateHistogram) {
410
+ builder.add (" histogram" , VPackValue (VPackValueType::Object));
411
+ setupHistogram (pp);
347
412
}
348
- pp << std::endl;
349
413
350
414
for (uint64_t j = 0 ; j < _runs; j++) {
351
415
status (" starting threads..." );
@@ -365,7 +429,7 @@ void BenchFeature::start() {
365
429
auto thread = std::make_unique<BenchmarkThread>(
366
430
server (), benchmark.get (), &startCondition, &BenchFeature::updateStartCounter,
367
431
static_cast <int >(i), _batchSize, &operationsCounter, client,
368
- _keepAlive, _async, _histogramIntervalSize, _histogramNumIntervals);
432
+ _keepAlive, _async, _histogramIntervalSize, _histogramNumIntervals, _generateHistogram );
369
433
thread->setOffset (i * realStep);
370
434
thread->start ();
371
435
threads.push_back (std::move (thread));
@@ -432,45 +496,31 @@ void BenchFeature::start() {
432
496
requestTime,
433
497
});
434
498
435
- for (size_t i = 0 ; i < static_cast <size_t >(_concurrency); ++i) {
436
- if (_duration != 0 ) {
437
- _realOperations += threads[i]->_counter ;
438
- }
439
-
440
- totalStats.add (threads[i]->stats ());
499
+ updateStatsValues (pp, builder, threads, totalStats);
441
500
442
- double scope;
443
- auto res = threads[i]->getPercentiles (_percentiles, scope);
501
+ threads.clear ();
502
+ }
503
+ if (_generateHistogram) {
504
+ builder.close ();
505
+ }
444
506
445
- builder->add (std::to_string (i), VPackValue (VPackValueType::Object));
446
- size_t j = 0 ;
507
+ std::cout << ' \n ' ;
447
508
448
- pp << " " << std::left << std::setfill ( ' 0 ' ) << std::fixed << std::setw ( 8 )
449
- << std::setprecision ( 6 ) << (threads[i]-> _histogramIntervalSize * 1000 )
450
- << std::setw ( 0 ) << " ms " ;
509
+ std::sort ( std::begin (results), std::end (results),
510
+ [](BenchRunResult const & a, BenchRunResult const & b )
511
+ { return a. _time < b. _time ; }) ;
451
512
452
- builder-> add ( " IntervalSize " , VPackValue (threads[i]-> _histogramIntervalSize ) );
513
+ report (client, results, totalStats, pp. str (), builder );
453
514
454
- for (auto time : res) {
455
- builder->add (std::to_string (_percentiles[j]), VPackValue (time ));
456
- pp << " " << std::left << std::setfill (' 0' ) << std::fixed << std::setw (8 )
457
- << std::setprecision (6 ) << (time * 1000 ) << std::setw (0 ) << " ms" ;
458
- j++;
459
- }
515
+ builder.close ();
460
516
461
- builder->close ();
462
- pp << std::endl;
463
- }
464
- threads.clear ();
517
+ if (!_jsonReportFile.empty ()) {
518
+ auto json = builder.toJson ();
519
+ TRI_WriteFile (_jsonReportFile.c_str (), json.c_str (), json.length ());
465
520
}
466
521
467
- std::cout << std::endl;
468
- builder->close ();
469
-
470
- report (client, results, totalStats, pp.str (), *builder);
471
-
472
522
if (!ok) {
473
- std::cout << " At least one of the runs produced failures!" << std::endl ;
523
+ std::cout << " At least one of the runs produced failures!" << ' \n ' ;
474
524
}
475
525
476
526
benchmark->tearDown ();
@@ -482,10 +532,13 @@ void BenchFeature::start() {
482
532
*_result = ret;
483
533
}
484
534
485
- bool BenchFeature::report (ClientFeature& client, std::vector<BenchRunResult> results,
535
+ void BenchFeature::report (ClientFeature& client, std::vector<BenchRunResult> const & results,
486
536
BenchmarkStats const & stats,
487
537
std::string const & histogram, VPackBuilder& builder) {
488
- std::cout << std::endl;
538
+
539
+ if (_generateHistogram) {
540
+ std::cout << histogram << ' \n ' ;
541
+ }
489
542
490
543
std::cout << " Total number of operations: " << _realOperations << " , runs: " << _runs
491
544
<< " , keep alive: " << (_keepAlive ? " yes" : " no" )
@@ -513,10 +566,13 @@ bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> res
513
566
builder.add (" database" , VPackValue (client.databaseName ()));
514
567
builder.add (" collection" , VPackValue (_collection));
515
568
516
- std::sort (results.begin (), results.end (),
517
- [](BenchRunResult a, BenchRunResult b) { return a._time < b._time ; });
569
+ TRI_ASSERT (std::is_sorted (std::begin (results), std::end (results),
570
+ [](BenchRunResult const & a, BenchRunResult const & b)
571
+ { return a._time < b._time ; }));
572
+
518
573
519
574
BenchRunResult output{0 , 0 , 0 , 0 };
575
+
520
576
if (_runs > 1 ) {
521
577
size_t size = results.size ();
522
578
@@ -556,31 +612,24 @@ bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> res
556
612
printResult (output, builder);
557
613
builder.close ();
558
614
559
- std::cout << " Min request time: " << std::setprecision (6 )
615
+ std::cout << " Min request time: " << std::setprecision (4 )
560
616
<< (stats.min * 1000 ) << " ms" << std::endl
561
- << " Avg request time: " << std::setprecision (6 )
617
+ << " Avg request time: " << std::setprecision (4 )
562
618
<< (stats.avg () * 1000 ) << " ms" << std::endl
563
- << " Max request time: " << std::setprecision (6 )
619
+ << " Max request time: " << std::setprecision (4 )
564
620
<< (stats.max * 1000 ) << " ms" << std::endl
565
- << std::endl;
566
-
567
- std::cout << histogram;
621
+ << ' \n ' ;
568
622
569
623
builder.add (" min" , VPackValue (stats.min ));
570
624
builder.add (" avg" , VPackValue (stats.avg ()));
571
625
builder.add (" max" , VPackValue (stats.max ));
572
- builder.close ();
573
626
574
- if (!_jsonReportFile.empty ()) {
575
- auto json = builder.toJson ();
576
- TRI_WriteFile (_jsonReportFile.c_str (), json.c_str (), json.length ());
577
- }
578
627
579
- if (_junitReportFile.empty ()) {
580
- return true ;
628
+
629
+ if (!_junitReportFile.empty ()) {
630
+ writeJunitReport (output);
581
631
}
582
632
583
- return writeJunitReport (output);
584
633
}
585
634
586
635
bool BenchFeature::writeJunitReport (BenchRunResult const & result) {
0 commit comments