Permalink
Browse files

Add ping-pong benchmark

On Linux I'm getting

    ping_pongs: 22807 pings
  • Loading branch information...
1 parent 2cbcbdd commit 1a99dcc980d273d04a539b3baf30191a46e76cb6 @ry ry committed Apr 19, 2011
Showing with 185 additions and 4 deletions.
  1. +2 −2 Makefile
  2. +1 −1 test/benchmark-dummy.c
  3. +5 −1 test/benchmark-list.h
  4. +166 −0 test/benchmark-ping-pongs.c
  5. +11 −0 test/echo-server.c
View
@@ -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
@@ -25,4 +25,4 @@
BENCHMARK_IMPL(dummy) {
LOG("23487 foos/bar\n");
return 0;
-}
+}
View
@@ -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
View
@@ -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
@@ -144,3 +144,14 @@ TEST_IMPL(echo_server) {
oio_run();
return 0;
}
+
+/* FIXME: Ugly. Isn't there a better way to do this? */
@piscisaureus

piscisaureus Apr 19, 2011

Member

Sure there's a better way. I didn't think about this...

+BENCHMARK_IMPL(echo_server) {
+ oio_init();
+ if (echo_start(TEST_PORT))
+ return 1;
+
+ fprintf(stderr, "Listening!\n");
+ oio_run();
+ return 0;
+}

2 comments on commit 1a99dcc

Contributor

ry replied Apr 19, 2011

of course with large variance...

http://tinyclouds.org/images/ping-pongs-linux.png

Member

piscisaureus replied Apr 19, 2011

FWIW, the same benchmark on windows:

http://twitpic.com/4mrx0l

Please sign in to comment.