mirror of
https://github.com/savoirfairelinux/opendht.git
synced 2026-11-08 12:28:42 +00:00
179 lines
5.2 KiB
C++
179 lines
5.2 KiB
C++
// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
|
|
// SPDX-License-Identifier: MIT
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "tools_common.h"
|
|
#include <opendht/node.h>
|
|
|
|
extern "C" {
|
|
#include <gnutls/gnutls.h>
|
|
}
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
#include <atomic>
|
|
|
|
namespace dht {
|
|
namespace tests {
|
|
|
|
constexpr unsigned PINGPONG_MAX = 2048;
|
|
|
|
using clock = std::chrono::high_resolution_clock;
|
|
using duration = clock::duration;
|
|
|
|
void
|
|
print_usage()
|
|
{
|
|
std::cout << "Usage: perftest" << std::endl << std::endl;
|
|
std::cout << "perftest, a simple OpenDHT basic performance tester." << std::endl;
|
|
std::cout << "Report bugs to: https://opendht.net" << std::endl;
|
|
}
|
|
duration
|
|
benchPingPong(unsigned netSize, unsigned n_parallel)
|
|
{
|
|
DhtRunner::Config config {};
|
|
config.dht_config.node_config.max_peer_req_per_sec = -1;
|
|
config.dht_config.node_config.max_req_per_sec = -1;
|
|
config.dht_config.node_config.max_crypto_per_sec = -1;
|
|
config.dht_config.node_config.max_peer_crypto_per_sec = -1;
|
|
|
|
DhtRunner ping_node, pong_node;
|
|
|
|
std::vector<std::pair<InfoHash, InfoHash>> locs;
|
|
locs.reserve(n_parallel);
|
|
for (unsigned i = 0; i < n_parallel; i++) {
|
|
auto loc_ping = InfoHash::get("toto" + std::to_string(i));
|
|
locs.emplace_back(loc_ping, InfoHash::get(loc_ping.toString()));
|
|
}
|
|
|
|
ping_node.run(0, config);
|
|
pong_node.run(0, config);
|
|
auto bindAddr = ping_node.getBound();
|
|
pong_node.bootstrap(bindAddr);
|
|
|
|
std::vector<std::unique_ptr<DhtRunner>> nodes;
|
|
nodes.reserve(netSize);
|
|
for (unsigned i = 0; i < netSize; i++) {
|
|
auto node = std::make_unique<DhtRunner>();
|
|
node->run(0, config);
|
|
node->bootstrap(bindAddr);
|
|
nodes.emplace_back(std::move(node));
|
|
}
|
|
|
|
// std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
|
|
std::condition_variable cv;
|
|
unsigned i {0};
|
|
std::mutex m;
|
|
|
|
unsigned max = PINGPONG_MAX * n_parallel;
|
|
|
|
auto ping = [&](DhtRunner& node, InfoHash h) {
|
|
std::lock_guard lk(m);
|
|
if (i < max) {
|
|
i++;
|
|
node.put(h, Value("hey"));
|
|
}
|
|
cv.notify_one();
|
|
};
|
|
|
|
for (unsigned i = 0; i < n_parallel; i++) {
|
|
ping_node.listen(locs[i].first, [&, i](const std::shared_ptr<Value>&) {
|
|
ping(pong_node, locs[i].second);
|
|
return true;
|
|
});
|
|
pong_node.listen(locs[i].second, [&, i](const std::shared_ptr<Value>&) {
|
|
ping(ping_node, locs[i].first);
|
|
return true;
|
|
});
|
|
}
|
|
|
|
auto start = clock::now();
|
|
|
|
for (unsigned i = 0; i < n_parallel; i++)
|
|
ping(pong_node, locs[i].first);
|
|
|
|
{
|
|
std::unique_lock lk(m);
|
|
if (not cv.wait_for(lk, std::chrono::minutes(1), [&]() { return i == max; })) {
|
|
throw std::runtime_error(std::string("Timeout: ") + std::to_string(i));
|
|
}
|
|
}
|
|
|
|
auto end = clock::now();
|
|
|
|
for (auto& node : nodes)
|
|
node->shutdown();
|
|
ping_node.shutdown();
|
|
pong_node.shutdown();
|
|
|
|
for (auto& node : nodes)
|
|
node->join();
|
|
ping_node.join();
|
|
pong_node.join();
|
|
|
|
return end - start;
|
|
}
|
|
|
|
} // namespace tests
|
|
} // namespace dht
|
|
|
|
int
|
|
main(int argc, char** argv)
|
|
{
|
|
using namespace dht::tools;
|
|
using namespace dht::tests;
|
|
#ifdef _MSC_VER
|
|
if (auto err = gnutls_global_init()) {
|
|
std::cerr << "Failed to initialize GnuTLS: " << gnutls_strerror(err) << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
#endif
|
|
auto params = parseArgs(argc, argv);
|
|
if (params.help) {
|
|
print_usage();
|
|
return 0;
|
|
}
|
|
|
|
duration totalTime {0};
|
|
unsigned totalOps {0};
|
|
|
|
for (unsigned nparallel = 1; nparallel <= 32; nparallel *= 2) {
|
|
unsigned max = PINGPONG_MAX * nparallel;
|
|
std::vector<duration> results {};
|
|
results.reserve(8);
|
|
duration total {0};
|
|
for (unsigned i = 2; i < 32; i *= 2) {
|
|
auto dt = benchPingPong(i - 2, nparallel);
|
|
std::cout << "Network size: " << i << std::endl;
|
|
std::cout << max << " ping-pong done, took " << dht::print_duration(dt) << std::endl;
|
|
std::cout << dht::print_duration(dt / max) << " per rt, " << max / std::chrono::duration<double>(dt).count()
|
|
<< " ping per s" << std::endl
|
|
<< std::endl;
|
|
total += dt;
|
|
totalOps += max;
|
|
results.emplace_back(dt);
|
|
}
|
|
|
|
totalTime += total;
|
|
|
|
std::cout << "Total for " << nparallel << std::endl;
|
|
auto totNum = max * results.size();
|
|
std::cout << totNum << " ping-pong done, took " << dht::print_duration(total) << std::endl;
|
|
std::cout << dht::print_duration(total / totNum) << " per rt, "
|
|
<< totNum / std::chrono::duration<double>(total).count() << " ping per s" << std::endl
|
|
<< std::endl;
|
|
}
|
|
|
|
std::cout << std::endl << "Grand total: " << dht::print_duration(totalTime) << " for " << totalOps << std::endl;
|
|
std::cout << dht::print_duration(totalTime / totalOps) << " per rt, "
|
|
<< totalOps / std::chrono::duration<double>(totalTime).count() << " ping per s" << std::endl
|
|
<< std::endl;
|
|
|
|
#ifdef _MSC_VER
|
|
gnutls_global_deinit();
|
|
#endif
|
|
return 0;
|
|
}
|