1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2026 The TokTok team.
*/
#include <benchmark/benchmark.h>
#include <cstdlib>
#include <vector>
#include "ev_test_util.hh"
#include "logger.h"
#include "net.h"
#include "os_event.h"
#include "os_memory.h"
#include "os_network.h"
namespace {
class EvBenchFixture : public benchmark::Fixture {
public:
void SetUp(const ::benchmark::State &state) override
{
if (os_network() == nullptr) {
setup_error = "os_network failed";
return;
}
mem = os_memory();
log = logger_new(mem);
// We don't want log output during benchmark
ev = os_event_new(mem, log);
}
void TearDown(const ::benchmark::State &state) override
{
for (size_t i = 0; i < sockets_r.size(); ++i) {
close_pair(sockets_r[i], sockets_w[i]);
}
sockets_r.clear();
sockets_w.clear();
ev_kill(ev);
logger_kill(log);
}
const Memory *mem = nullptr;
Logger *log = nullptr;
Ev *ev = nullptr;
std::vector<Socket> sockets_r;
std::vector<Socket> sockets_w;
int tag = 1;
std::string setup_error;
};
// Specialized SetUp to handle socket creation based on range
class EvBenchSocketsFixture : public EvBenchFixture {
public:
void SetUp(const ::benchmark::State &state) override
{
EvBenchFixture::SetUp(state);
if (!setup_error.empty()) {
return;
}
const int num_sockets = state.range(0);
for (int i = 0; i < num_sockets; ++i) {
Socket r{}, w{};
if (create_pair(&r, &w) != 0) {
setup_error = "Failed to create socket pair";
return;
}
sockets_r.push_back(r);
sockets_w.push_back(w);
if (!ev_add(ev, r, EV_READ, &tag)) {
setup_error = "Failed to add socket to event loop";
return;
}
}
}
};
BENCHMARK_DEFINE_F(EvBenchSocketsFixture, EventLoopRun)(benchmark::State &state)
{
if (!setup_error.empty()) {
state.SkipWithError(setup_error.c_str());
return;
}
// Sockets are already created in SetUp.
Ev_Result results[1];
char buf = 'x';
// We trigger the last socket
if (write_socket(sockets_w.back(), &buf, 1) != 1) {
state.SkipWithError("Failed to write to socket");
return;
}
for (auto _ : state) {
int32_t n = ev_run(ev, results, 1, 100);
if (n != 1) {
state.SkipWithError("ev_run did not return event");
break;
}
}
}
BENCHMARK_REGISTER_F(EvBenchSocketsFixture, EventLoopRun)->Range(8, 1024);
BENCHMARK_DEFINE_F(EvBenchSocketsFixture, EventLoopMultipleActive)(benchmark::State &state)
{
if (!setup_error.empty()) {
state.SkipWithError(setup_error.c_str());
return;
}
const int num_sockets = state.range(0);
const int num_active = state.range(1);
if (num_active > num_sockets) {
state.SkipWithError("Active sockets cannot exceed total sockets");
return;
}
char buf = 'x';
// Trigger 'num_active' sockets
for (int i = 0; i < num_active; ++i) {
if (write_socket(sockets_w[i], &buf, 1) != 1) {
state.SkipWithError("Failed to write socket");
return;
}
}
std::vector<Ev_Result> results(num_active);
for (auto _ : state) {
int32_t n = ev_run(ev, results.data(), num_active, 100);
if (n != num_active) {
state.SkipWithError("ev_run did not return expected number of events");
break;
}
}
}
// Fix N=1024, vary M
BENCHMARK_REGISTER_F(EvBenchSocketsFixture, EventLoopMultipleActive)
->Args({1024, 1})
->Args({1024, 10})
->Args({1024, 100})
->Args({1024, 1024});
} // namespace
BENCHMARK_MAIN();
|