2024-03-08 14:03:37 +08:00

143 lines
3.0 KiB
C++

// Benchmark inspired by libevent/test/bench.c
// See also: http://libev.schmorp.de/bench.html
#include "muduo/base/Logging.h"
#include "muduo/base/Thread.h"
#include "muduo/net/Channel.h"
#include "muduo/net/EventLoop.h"
#include <stdio.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <unistd.h>
using namespace muduo;
using namespace muduo::net;
std::vector<int> g_pipes;
int numPipes;
int numActive;
int numWrites;
EventLoop* g_loop;
std::vector<std::unique_ptr<Channel>> g_channels;
int g_reads, g_writes, g_fired;
void readCallback(Timestamp, int fd, int idx)
{
char ch;
g_reads += static_cast<int>(::recv(fd, &ch, sizeof(ch), 0));
if (g_writes > 0)
{
int widx = idx+1;
if (widx >= numPipes)
{
widx -= numPipes;
}
::send(g_pipes[2 * widx + 1], "m", 1, 0);
g_writes--;
g_fired++;
}
if (g_fired == g_reads)
{
g_loop->quit();
}
}
std::pair<int, int> runOnce()
{
Timestamp beforeInit(Timestamp::now());
for (int i = 0; i < numPipes; ++i)
{
Channel& channel = *g_channels[i];
channel.setReadCallback(std::bind(readCallback, _1, channel.fd(), i));
channel.enableReading();
}
int space = numPipes / numActive;
space *= 2;
for (int i = 0; i < numActive; ++i)
{
::send(g_pipes[i * space + 1], "m", 1, 0);
}
g_fired = numActive;
g_reads = 0;
g_writes = numWrites;
Timestamp beforeLoop(Timestamp::now());
g_loop->loop();
Timestamp end(Timestamp::now());
int iterTime = static_cast<int>(end.microSecondsSinceEpoch() - beforeInit.microSecondsSinceEpoch());
int loopTime = static_cast<int>(end.microSecondsSinceEpoch() - beforeLoop.microSecondsSinceEpoch());
return std::make_pair(iterTime, loopTime);
}
int main(int argc, char* argv[])
{
numPipes = 100;
numActive = 1;
numWrites = 100;
int c;
while ((c = getopt(argc, argv, "n:a:w:")) != -1)
{
switch (c)
{
case 'n':
numPipes = atoi(optarg);
break;
case 'a':
numActive = atoi(optarg);
break;
case 'w':
numWrites = atoi(optarg);
break;
default:
fprintf(stderr, "Illegal argument \"%c\"\n", c);
return 1;
}
}
struct rlimit rl;
rl.rlim_cur = rl.rlim_max = numPipes * 2 + 50;
if (::setrlimit(RLIMIT_NOFILE, &rl) == -1)
{
perror("setrlimit");
//return 1; // comment out this line if under valgrind
}
g_pipes.resize(2 * numPipes);
for (int i = 0; i < numPipes; ++i)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, &g_pipes[i*2]) == -1)
{
perror("pipe");
return 1;
}
}
EventLoop loop;
g_loop = &loop;
for (int i = 0; i < numPipes; ++i)
{
Channel* channel = new Channel(&loop, g_pipes[i*2]);
g_channels.emplace_back(channel);
}
for (int i = 0; i < 25; ++i)
{
std::pair<int, int> t = runOnce();
printf("%8d %8d\n", t.first, t.second);
}
for (const auto& channel : g_channels)
{
channel->disableAll();
channel->remove();
}
g_channels.clear();
}