Skip to content

Commit 1e02f2b

Browse files
authored
Feature/apm 173 (#14830)
1 parent 4fd30a6 commit 1e02f2b

38 files changed

+302
-280
lines changed

CHANGELOG

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
devel
22
-----
33

4+
* APM-173: Now, arangobench, arangodump and arangorestore support multiple
5+
coordinators, so the flag `--server.endpoint` can be used multiple times,
6+
as in the example below:
7+
8+
arangobench \
9+
--server.endpoint tcp://[::1]::8529 \
10+
--server.endpoint tcp://[::1]::8530 \
11+
--server.endpoint tcp://[::1]::8531
12+
13+
This does not compromise the use of the other client tools, which preserve
14+
the behavior of having one coordinator.
15+
416
* The server now has two flags to control the escaping control and Unicode
517
characters in the log. The flag `--log.escape` is now deprecated and, instead,
618
the new flags `--log.escape-control-chars` and `--log.escape-unicode-chars`

arangosh/Backup/BackupFeature.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ arangodb::Result waitForRestart(arangodb::ClientManager& clientManager,
162162
while (timeSinceStart() < maxWaitForRestart) {
163163
std::unique_ptr<arangodb::httpclient::SimpleHttpClient> client;
164164
try {
165-
result = clientManager.getConnectedClient(client, true, false, false, true);
165+
result = clientManager.getConnectedClient(client, true, false, false, true, 0);
166166
if (result.ok() && client != nullptr) {
167167
double uptime = 0.0;
168168
result = ::getUptime(*client, uptime);
@@ -860,7 +860,7 @@ void BackupFeature::validateOptions(std::shared_ptr<options::ProgramOptions> opt
860860
void BackupFeature::start() {
861861
Result result;
862862
std::unique_ptr<httpclient::SimpleHttpClient> client =
863-
_clientManager.getConnectedClient(false, true, true);
863+
_clientManager.getConnectedClient(false, true, true, 0);
864864
if (_options.operation == OperationList) {
865865
result = ::executeList(*client, _options);
866866
} else if (_options.operation == OperationCreate) {

arangosh/Benchmark/BenchFeature.cpp

Lines changed: 71 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
#include "BenchFeature.h"
3030

3131
#include <ctime>
32-
#include <iomanip>
3332
#include <fstream>
33+
#include <iomanip>
3434
#include <iostream>
3535

3636
#ifdef TRI_HAVE_UNISTD_H
@@ -39,19 +39,20 @@
3939

4040
#include "ApplicationFeatures/ApplicationServer.h"
4141
#include "Basics/FileUtils.h"
42+
#include "Basics/NumberOfCores.h"
4243
#include "Basics/StaticStrings.h"
4344
#include "Basics/StringUtils.h"
4445
#include "Basics/Utf8Helper.h"
4546
#include "Basics/application-exit.h"
4647
#include "Basics/files.h"
4748
#include "Basics/system-functions.h"
48-
#include "Logger/Logger.h"
49-
#include "Logger/LogMacros.h"
5049
#include "Benchmark/BenchmarkCounter.h"
5150
#include "Benchmark/BenchmarkOperation.h"
5251
#include "Benchmark/BenchmarkStats.h"
5352
#include "Benchmark/BenchmarkThread.h"
5453
#include "FeaturePhases/BasicFeaturePhaseClient.h"
54+
#include "Logger/LogMacros.h"
55+
#include "Logger/Logger.h"
5556
#include "ProgramOptions/ProgramOptions.h"
5657
#include "ProgramOptions/Section.h"
5758
#include "Shell/ClientFeature.h"
@@ -75,7 +76,7 @@ using namespace arangodb::rest;
7576

7677
BenchFeature::BenchFeature(application_features::ApplicationServer& server, int* result)
7778
: ApplicationFeature(server, "Bench"),
78-
_concurrency(1),
79+
_concurrency(NumberOfCores::getValue()),
7980
_operations(1000),
8081
_realOperations(0),
8182
_batchSize(0),
@@ -139,11 +140,10 @@ void BenchFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
139140
options->addOption("--histogram.num-intervals",
140141
"number of buckets (resolution)",
141142
new UInt64Parameter(&_histogramNumIntervals));
142-
options->addOption("--histogram.percentiles",
143-
"which percentiles to calculate",
143+
options->addOption("--histogram.percentiles", "which percentiles to calculate",
144144
new VectorParameter<DoubleParameter>(&_percentiles),
145145
arangodb::options::makeDefaultFlags(options::Flags::FlushOnFirst));
146-
146+
147147
options->addOption("--async", "send asynchronous requests", new BooleanParameter(&_async));
148148

149149
options->addOption("--concurrency",
@@ -178,7 +178,8 @@ void BenchFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
178178
new BooleanParameter(&_waitForSync));
179179

180180
options->addOption("--create-database",
181-
"whether we should create the database specified via the server connection",
181+
"whether we should create the database specified via the "
182+
"server connection",
182183
new BooleanParameter(&_createDatabase));
183184

184185
options->addOption("--duration",
@@ -216,16 +217,25 @@ void BenchFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
216217
options->addOption("--progress", "log intermediate progress",
217218
new BooleanParameter(&_progress));
218219

219-
options->addOption("--custom-query", "the query to be used in the 'custom-query' testcase",
220-
new StringParameter(&_customQuery)).setIntroducedIn(30800);
221-
222-
options->addOption("--custom-query-file", "path to a file with the query to be used in the 'custom-query' testcase. "
223-
"If --custom-query is specified as well, it has higher priority.",
224-
new StringParameter(&_customQueryFile)).setIntroducedIn(30800);
225-
220+
options
221+
->addOption("--custom-query",
222+
"the query to be used in the 'custom-query' testcase",
223+
new StringParameter(&_customQuery))
224+
.setIntroducedIn(30800);
225+
226+
options
227+
->addOption(
228+
"--custom-query-file",
229+
"path to a file with the query to be used in the 'custom-query' "
230+
"testcase. "
231+
"If --custom-query is specified as well, it has higher priority.",
232+
new StringParameter(&_customQueryFile))
233+
.setIntroducedIn(30800);
234+
226235
options->addOption("--quiet", "suppress status messages", new BooleanParameter(&_quiet));
227-
228-
options->addObsoleteOption("--verbose", "print out replies if the HTTP header indicates DB errors", false);
236+
237+
options->addObsoleteOption(
238+
"--verbose", "print out replies if the HTTP header indicates DB errors", false);
229239
}
230240

231241
void BenchFeature::status(std::string const& value) {
@@ -241,8 +251,8 @@ void BenchFeature::updateStartCounter() { ++_started; }
241251
int BenchFeature::getStartCounter() { return _started; }
242252

243253
void BenchFeature::start() {
244-
sort(_percentiles.begin(), _percentiles.end());
245-
254+
std::sort(_percentiles.begin(), _percentiles.end());
255+
246256
if (!_jsonReportFile.empty() && FileUtils::exists(_jsonReportFile)) {
247257
LOG_TOPIC("ee2a4", FATAL, arangodb::Logger::BENCH)
248258
<< "file already exists: '" << _jsonReportFile << "' - won't overwrite it.";
@@ -261,14 +271,13 @@ void BenchFeature::start() {
261271
b.openObject();
262272
b.add("name", VPackValue(normalizeUtf8ToNFC(connectDB)));
263273
b.close();
264-
274+
265275
std::unordered_map<std::string, std::string> headers;
266276
headers.emplace(StaticStrings::ContentTypeHeader, StaticStrings::MimeTypeVPack);
267277

268278
auto result = createDbClient->request(rest::RequestType::POST,
269-
"/_api/database",
270-
b.slice().startAs<char>(), b.slice().byteSize(),
271-
headers);
279+
"/_api/database", b.slice().startAs<char>(),
280+
b.slice().byteSize(), headers);
272281

273282
if (!result || result->wasHttpError()) {
274283
std::string msg;
@@ -278,7 +287,7 @@ void BenchFeature::start() {
278287
}
279288

280289
LOG_TOPIC("5cda8", FATAL, arangodb::Logger::BENCH)
281-
<< "failed to create the specified database: " << msg;
290+
<< "failed to create the specified database: " << msg;
282291
FATAL_ERROR_EXIT();
283292
}
284293

@@ -289,7 +298,8 @@ void BenchFeature::start() {
289298

290299
*_result = ret;
291300

292-
std::unique_ptr<BenchmarkOperation> benchmark = BenchmarkOperation::createBenchmark(_testCase, *this);
301+
std::unique_ptr<BenchmarkOperation> benchmark =
302+
BenchmarkOperation::createBenchmark(_testCase, *this);
293303

294304
if (benchmark == nullptr) {
295305
LOG_TOPIC("ee2a5", FATAL, arangodb::Logger::BENCH)
@@ -298,10 +308,11 @@ void BenchFeature::start() {
298308
}
299309

300310
LOG_TOPIC("69091", INFO, arangodb::Logger::BENCH)
301-
<< "Running test case '" << _testCase << "': " << benchmark->getDescription();
311+
<< "Running test case '" << _testCase << "': " << benchmark->getDescription();
302312
if (benchmark->isDeprecated()) {
303313
LOG_TOPIC("caf8a", WARN, arangodb::Logger::BENCH)
304-
<< "Please note: this test case is deprecated and will be removed in a future version.";
314+
<< "Please note: this test case is deprecated and will be removed in a "
315+
"future version.";
305316
}
306317

307318
if (_duration != 0) {
@@ -323,10 +334,10 @@ void BenchFeature::start() {
323334
// add some more offset so we don't get into trouble with threads of different
324335
// speed
325336
realStep += 10000;
326-
337+
327338
// aggregated stats for all runs
328339
BenchmarkStats totalStats;
329-
340+
330341
auto builder = std::make_shared<VPackBuilder>();
331342
builder->openObject();
332343
builder->add("histogram", VPackValue(VPackValueType::Object));
@@ -336,7 +347,8 @@ void BenchFeature::start() {
336347
std::stringstream pp;
337348
pp << "Interval/Percentile:";
338349
for (auto percentile : _percentiles) {
339-
pp << std::fixed << std::right << std::setw(12) << std::setprecision(2) << percentile << "%";
350+
pp << std::fixed << std::right << std::setw(12) << std::setprecision(2)
351+
<< percentile << "%";
340352
}
341353
pp << std::endl;
342354

@@ -356,11 +368,9 @@ void BenchFeature::start() {
356368

357369
for (uint64_t i = 0; i < _concurrency; ++i) {
358370
auto thread = std::make_unique<BenchmarkThread>(
359-
server(), benchmark.get(), &startCondition,
360-
&BenchFeature::updateStartCounter, static_cast<int>(i),
361-
_batchSize, &operationsCounter,
362-
client, _keepAlive, _async,
363-
_histogramIntervalSize, _histogramNumIntervals);
371+
server(), benchmark.get(), &startCondition, &BenchFeature::updateStartCounter,
372+
static_cast<int>(i), _batchSize, &operationsCounter, client,
373+
_keepAlive, _async, _histogramIntervalSize, _histogramNumIntervals);
364374
thread->setOffset(i * realStep);
365375
thread->start();
366376
threads.push_back(std::move(thread));
@@ -400,10 +410,11 @@ void BenchFeature::start() {
400410
}
401411

402412
if (_progress && numOperations >= nextReportValue) {
403-
LOG_TOPIC("c3604", INFO, arangodb::Logger::BENCH) << "number of operations: " << nextReportValue;
413+
LOG_TOPIC("c3604", INFO, arangodb::Logger::BENCH)
414+
<< "number of operations: " << nextReportValue;
404415
nextReportValue += stepValue;
405416
}
406-
417+
407418
std::this_thread::sleep_for(std::chrono::milliseconds(5));
408419
}
409420

@@ -476,7 +487,9 @@ void BenchFeature::start() {
476487
*_result = ret;
477488
}
478489

479-
bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> results, BenchmarkStats const& stats, std::string const& histogram, VPackBuilder& builder) {
490+
bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> results,
491+
BenchmarkStats const& stats,
492+
std::string const& histogram, VPackBuilder& builder) {
480493
std::cout << std::endl;
481494

482495
std::cout << "Total number of operations: " << _realOperations << ", runs: " << _runs
@@ -505,7 +518,6 @@ bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> res
505518
builder.add("database", VPackValue(client.databaseName()));
506519
builder.add("collection", VPackValue(_collection));
507520

508-
509521
std::sort(results.begin(), results.end(),
510522
[](BenchRunResult a, BenchRunResult b) { return a._time < b._time; });
511523

@@ -516,11 +528,11 @@ bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> res
516528
std::cout << std::endl;
517529
std::cout << "Printing fastest result" << std::endl;
518530
std::cout << "=======================" << std::endl;
519-
531+
520532
builder.add("fastestResults", VPackValue(VPackValueType::Object));
521533
printResult(results[0], builder);
522534
builder.close();
523-
535+
524536
std::cout << "Printing slowest result" << std::endl;
525537
std::cout << "=======================" << std::endl;
526538

@@ -549,16 +561,19 @@ bool BenchFeature::report(ClientFeature& client, std::vector<BenchRunResult> res
549561
printResult(output, builder);
550562
builder.close();
551563

552-
std::cout <<
553-
"Min request time: " << std::setprecision(6) << (stats.min * 1000) << "ms" << std::endl <<
554-
"Avg request time: " << std::setprecision(6) << (stats.avg() * 1000) << "ms" << std::endl <<
555-
"Max request time: " << std::setprecision(6) << (stats.max * 1000) << "ms" << std::endl << std::endl;
564+
std::cout << "Min request time: " << std::setprecision(6)
565+
<< (stats.min * 1000) << "ms" << std::endl
566+
<< "Avg request time: " << std::setprecision(6)
567+
<< (stats.avg() * 1000) << "ms" << std::endl
568+
<< "Max request time: " << std::setprecision(6)
569+
<< (stats.max * 1000) << "ms" << std::endl
570+
<< std::endl;
556571

557572
std::cout << histogram;
558573

559574
builder.add("min", VPackValue(stats.min));
560575
builder.add("avg", VPackValue(stats.avg()));
561-
builder.add("max", VPackValue(stats.max));
576+
builder.add("max", VPackValue(stats.max));
562577
builder.close();
563578

564579
if (!_jsonReportFile.empty()) {
@@ -617,25 +632,26 @@ void BenchFeature::printResult(BenchRunResult const& result, VPackBuilder& build
617632
builder.add("requestTime", VPackValue(result._requestTime));
618633
std::cout << "Request/response duration (per thread): " << std::fixed
619634
<< (result._requestTime / (double)_concurrency) << " s" << std::endl;
620-
builder.add("requestResponseDurationPerThread", VPackValue(result._requestTime / (double)_concurrency));
635+
builder.add("requestResponseDurationPerThread",
636+
VPackValue(result._requestTime / (double)_concurrency));
621637

622638
std::cout << "Time needed per operation: " << std::fixed
623639
<< (result._time / _realOperations) << " s" << std::endl;
624640
builder.add("timeNeededPerOperation", VPackValue(result._time / _realOperations));
625-
641+
626642
std::cout << "Time needed per operation per thread: " << std::fixed
627643
<< (result._time / (double)_realOperations * (double)_concurrency)
628644
<< " s" << std::endl;
629-
builder.add("timeNeededPerOperationPerThread", VPackValue(
630-
result._time / (double)_realOperations * (double)_concurrency));
631-
645+
builder.add("timeNeededPerOperationPerThread",
646+
VPackValue(result._time / (double)_realOperations * (double)_concurrency));
647+
632648
std::cout << "Operations per second rate: " << std::fixed
633649
<< ((double)_realOperations / result._time) << std::endl;
634-
builder.add("operationsPerSecondRate",
650+
builder.add("operationsPerSecondRate",
635651
VPackValue((double)_realOperations / result._time));
636-
637-
std::cout << "Elapsed time since start: " << std::fixed << result._time << " s"
638-
<< std::endl
652+
653+
std::cout << "Elapsed time since start: " << std::fixed << result._time
654+
<< " s" << std::endl
639655
<< std::endl;
640656
builder.add("timeSinceStart", VPackValue(result._time));
641657

arangosh/Benchmark/BenchmarkOperation.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct BenchmarkOperation {
6767
/// @brief build the HTTP request and set it's values (url, type and payload)
6868
/// inside RequestData.
6969
/// The caller must provide it and clean its values before the call
70-
virtual void buildRequest(int threadNumber, size_t threadCounter, size_t globalCounter, RequestData&) const = 0;
70+
virtual void buildRequest(size_t threadNumber, size_t threadCounter, size_t globalCounter, RequestData&) const = 0;
7171

7272
using BenchmarkFactory = std::function<std::unique_ptr<BenchmarkOperation>(BenchFeature&)>;
7373

0 commit comments

Comments
 (0)