From eb5cd17c7889ca2944fc6ae64bcd83041f6ada2d Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Tue, 30 Oct 2018 01:47:10 +0100 Subject: [PATCH] Add fast enough WebSocket benchmark --- benchmarks/Makefile | 2 + benchmarks/load_test.c | 147 +++++++++++++++++++++++++++++++++++++++++ src/WebSocket.h | 4 ++ src/WebSocketData.h | 4 ++ 4 files changed, 157 insertions(+) create mode 100644 benchmarks/Makefile create mode 100644 benchmarks/load_test.c create mode 100644 src/WebSocket.h create mode 100644 src/WebSocketData.h diff --git a/benchmarks/Makefile b/benchmarks/Makefile new file mode 100644 index 0000000..bd482ab --- /dev/null +++ b/benchmarks/Makefile @@ -0,0 +1,2 @@ +default: + clang -flto -O3 -DLIBUS_NO_SSL -I../uSockets/src ../uSockets/src/*.c ../uSockets/src/eventing/*.c load_test.c -o load_test diff --git a/benchmarks/load_test.c b/benchmarks/load_test.c new file mode 100644 index 0000000..f19af43 --- /dev/null +++ b/benchmarks/load_test.c @@ -0,0 +1,147 @@ +/* This is a simple yet efficient WebSocket server benchmark much like WRK */ + +#include +//#include "helper.h" + +#include +#include +#include + +// request eller upgradeRequest samt webSocketFrame + +unsigned char web_socket_request[26] = {130, 128 | 20, 1, 2, 3, 4}; + +char request[] = "GET / HTTP/1.1\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n" + "Host: server.example.com\r\n" + "Sec-WebSocket-Version: 13\r\n\r\n"; +char *host; +int port; +int connections; + +int responses; + +struct http_socket { + /* How far we have streamed our request */ + int offset; +}; + +/* We don't need any of these */ +void on_wakeup(struct us_loop *loop) { + +} + +void on_pre(struct us_loop *loop) { + +} + +/* This is not HTTP POST, it is merely an event emitted post loop iteration */ +void on_post(struct us_loop *loop) { + +} + +struct us_socket *on_http_socket_writable(struct us_socket *s) { + struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s); + + /* Stream whatever is remaining of the request */ + http_socket->offset += us_socket_write(s, web_socket_request + http_socket->offset, sizeof(web_socket_request) - http_socket->offset, 0); + + return s; +} + +struct us_socket *on_http_socket_close(struct us_socket *s) { + + printf("Closed!\n"); + + return s; +} + +struct us_socket *on_http_socket_end(struct us_socket *s) { + return us_socket_close(s); +} + +struct us_socket *on_http_socket_data(struct us_socket *s, char *data, int length) { + /* Get socket extension and the socket's context's extension */ + struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s); + struct http_context *http_context = (struct http_context *) us_socket_context_ext(us_socket_get_context(s)); + + /* We treat all data events as a response */ + http_socket->offset = us_socket_write(s, web_socket_request, sizeof(web_socket_request), 0); + + /* */ + responses++; + + //printf("Fick ett svar\n"); + + return s; +} + +struct us_socket *on_http_socket_open(struct us_socket *s, int is_client) { + struct http_socket *http_socket = (struct http_socket *) us_socket_ext(s); + + /* Reset offset */ + http_socket->offset = 0; + + /* Send a request */ + us_socket_write(s, request, sizeof(request) - 1, 0); + + if (--connections) { + us_socket_context_connect(us_socket_get_context(s), host, port, 0, sizeof(struct http_socket)); + } else { + printf("Running benchmark now...\n"); + + us_socket_timeout(s, LIBUS_TIMEOUT_GRANULARITY); + } + + return s; +} + +struct us_socket *on_http_socket_timeout(struct us_socket *s) { + /* Print current statistics */ + printf("Req/sec: %f\n", ((float)responses) / LIBUS_TIMEOUT_GRANULARITY); + + responses = 0; + us_socket_timeout(s, LIBUS_TIMEOUT_GRANULARITY); + + return s; +} + +int main(int argc, char **argv) { + + /* Parse host and port */ + if (argc != 4) { + printf("Usage: connections host port\n"); + return 0; + } + + port = atoi(argv[3]); + host = malloc(strlen(argv[2]) + 1); + memcpy(host, argv[2], strlen(argv[2]) + 1); + connections = atoi(argv[1]); + + /* Create the event loop */ + struct us_loop *loop = us_create_loop(1, on_wakeup, on_pre, on_post, 0); + + /* Create a socket context for HTTP */ +#ifndef LIBUS_NO_SSL + struct us_ssl_socket_context_options ssl_options = {}; + struct us_socket_context *http_context = us_create_ssl_socket_context(loop, 0, ssl_options); +#else + struct us_socket_context *http_context = us_create_socket_context(loop, 0); +#endif + + /* Set up event handlers */ + us_socket_context_on_open(http_context, on_http_socket_open); + us_socket_context_on_data(http_context, on_http_socket_data); + us_socket_context_on_writable(http_context, on_http_socket_writable); + us_socket_context_on_close(http_context, on_http_socket_close); + us_socket_context_on_timeout(http_context, on_http_socket_timeout); + us_socket_context_on_end(http_context, on_http_socket_end); + + /* Start making HTTP connections */ + us_socket_context_connect(http_context, host, port, 0, sizeof(struct http_socket)); + + us_loop_run(loop); +} diff --git a/src/WebSocket.h b/src/WebSocket.h new file mode 100644 index 0000000..872b71b --- /dev/null +++ b/src/WebSocket.h @@ -0,0 +1,4 @@ +#ifndef WEBSOCKET_H +#define WEBSOCKET_H + +#endif // WEBSOCKET_H diff --git a/src/WebSocketData.h b/src/WebSocketData.h new file mode 100644 index 0000000..a8c3d3d --- /dev/null +++ b/src/WebSocketData.h @@ -0,0 +1,4 @@ +#ifndef WEBSOCKETDATA_H +#define WEBSOCKETDATA_H + +#endif // WEBSOCKETDATA_H