Add ping-pong benchmark

On Linux I'm getting

    ping_pongs: 22807 pings
This commit is contained in:
Ryan Dahl 2011-04-18 23:51:45 -07:00
parent 2cbcbdd1a4
commit 1a99dcc980
5 changed files with 185 additions and 4 deletions

View File

@ -21,9 +21,9 @@
all: oio.a test/run-tests test/run-benchmarks
CFLAGS=-ansi -g
LINKFLAGS=-g -lm
LINKFLAGS=-lm
TESTS=test/echo-server.c test/test-*.c
BENCHMARKS=test/benchmark-*.c
BENCHMARKS=test/echo-server.c test/benchmark-*.c
test/run-tests: test/*.h test/run-tests.c test/runner.c test/runner-unix.c $(TESTS) oio.a
$(CC) $(CFLAGS) $(LINKFLAGS) -o test/run-tests test/run-tests.c \

View File

@ -25,4 +25,4 @@
BENCHMARK_IMPL(dummy) {
LOG("23487 foos/bar\n");
return 0;
}
}

View File

@ -19,8 +19,12 @@
* IN THE SOFTWARE.
*/
BENCHMARK_DECLARE (echo_server)
BENCHMARK_DECLARE (ping_pongs)
BENCHMARK_DECLARE (dummy)
TASK_LIST_START
BENCHMARK_ENTRY (dummy)
TASK_LIST_END
BENCHMARK_ENTRY (ping_pongs)
BENCHMARK_HELPER (ping_pongs, echo_server)
TASK_LIST_END

166
test/benchmark-ping-pongs.c Normal file
View File

@ -0,0 +1,166 @@
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "../oio.h"
#include "task.h"
#include <stdlib.h>
#include <stdio.h>
static int completed_pingers = 0;
static int64_t start_time;
/* Run the benchmark for this many ms */
#define TIME 1000
/* 64 bytes is enough for a pinger */
#define BUFSIZE 1024
static char PING[] = "PING\n";
typedef struct {
int pongs;
int state;
oio_handle handle;
oio_req connect_req;
oio_req read_req;
oio_buf buf;
char read_buffer[BUFSIZE];
} pinger_t;
void pinger_try_read(pinger_t* pinger);
void pinger_on_close(oio_handle* handle, oio_err err) {
pinger_t* pinger = (pinger_t*)handle->data;
printf("%d pings\n", pinger->pongs);
ASSERT(!err);
free(pinger);
completed_pingers++;
}
void pinger_after_write(oio_req *req) {
free(req);
}
static void pinger_write_ping(pinger_t* pinger) {
oio_req *req;
req = (oio_req*)malloc(sizeof(*req));
oio_req_init(req, &pinger->handle, pinger_after_write);
if (oio_write2(req, (char*)&PING)) {
FATAL("oio_write2 failed");
}
}
static void pinger_after_read(oio_req* req, size_t nread) {
unsigned int i;
pinger_t* pinger;
pinger = (pinger_t*)req->handle->data;
if (nread == 0) {
puts("got EOF");
oio_close(&pinger->handle);
return;
}
/* Now we count the pings */
for (i = 0; i < nread; i++) {
ASSERT(pinger->buf.base[i] == PING[pinger->state]);
pinger->state = (pinger->state + 1) % (sizeof(PING) - 1);
if (pinger->state == 0) {
pinger->pongs++;
if (oio_now() - start_time > TIME) {
oio_close(&pinger->handle);
return;
} else {
pinger_write_ping(pinger);
}
}
}
pinger_try_read(pinger);
}
void pinger_try_read(pinger_t* pinger) {
oio_req_init(&pinger->read_req, &pinger->handle, pinger_after_read);
oio_read(&pinger->read_req, &pinger->buf, 1);
}
void pinger_on_connect(oio_req *req, oio_err err) {
pinger_t *pinger = (pinger_t*)req->handle->data;
ASSERT(!err);
pinger_try_read(pinger);
pinger_write_ping(pinger);
}
void pinger_new() {
int r;
struct sockaddr_in client_addr = oio_ip4_addr("0.0.0.0", 0);
struct sockaddr_in server_addr = oio_ip4_addr("127.0.0.1", TEST_PORT);
pinger_t *pinger;
pinger = (pinger_t*)malloc(sizeof(*pinger));
pinger->state = 0;
pinger->pongs = 0;
pinger->buf.len = BUFSIZE;
pinger->buf.base = (char*)&pinger->read_buffer;
/* Try to connec to the server and do NUM_PINGS ping-pongs. */
r = oio_tcp_init(&pinger->handle, pinger_on_close, (void*)pinger);
ASSERT(!r);
/* We are never doing multiple reads/connects at a time anyway. */
/* so these handles can be pre-initialized. */
oio_req_init(&pinger->connect_req, &pinger->handle, pinger_on_connect);
oio_bind(&pinger->handle, (struct sockaddr*)&client_addr);
r = oio_connect(&pinger->connect_req, (struct sockaddr*)&server_addr);
ASSERT(!r);
}
BENCHMARK_IMPL(ping_pongs) {
oio_init();
start_time = oio_now();
pinger_new();
oio_run();
ASSERT(completed_pingers == 1);
return 0;
}

View File

@ -144,3 +144,14 @@ TEST_IMPL(echo_server) {
oio_run();
return 0;
}
/* FIXME: Ugly. Isn't there a better way to do this? */
BENCHMARK_IMPL(echo_server) {
oio_init();
if (echo_start(TEST_PORT))
return 1;
fprintf(stderr, "Listening!\n");
oio_run();
return 0;
}