From 7bf48e3aaa38ebe70389a97a00444b31a92ac607 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Fri, 25 Sep 2020 15:07:27 -0400 Subject: [PATCH] feat: WIP --- runtime/Makefile | 20 +-- runtime/include/libuv_callbacks.h | 1 + runtime/include/sandbox.h | 3 +- runtime/src/current_sandbox.c | 2 +- runtime/src/http_parser_settings.c | 129 +++++++++++++++--- runtime/src/sandbox.c | 65 +++++---- runtime/tests/mixed_preemption/debug.sh | 19 +++ runtime/tests/mixed_preemption/demo.sh | 33 +++++ runtime/tests/mixed_preemption/post.lua | 43 ++++++ runtime/tests/mixed_preemption/res/fib10.txt | 107 +++++++++++++++ .../test_mixed_preemption.json | 70 ++++++++++ 11 files changed, 427 insertions(+), 65 deletions(-) create mode 100755 runtime/tests/mixed_preemption/debug.sh create mode 100755 runtime/tests/mixed_preemption/demo.sh create mode 100644 runtime/tests/mixed_preemption/post.lua create mode 100644 runtime/tests/mixed_preemption/res/fib10.txt create mode 100644 runtime/tests/mixed_preemption/test_mixed_preemption.json diff --git a/runtime/Makefile b/runtime/Makefile index 3b4e15f..dbdc3ff 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -12,7 +12,8 @@ CC_OPTIONS = -O3 -flto -g -pthread -D_GNU_SOURCE BINARY_NAME=sledgert # Number of Cores. Options: {2...N or TOTAL_CORES} -NCORES = ${TOTAL_CORES} +# NCORES = ${TOTAL_CORES} +NCORES = 2 # Options: {USE_MEM_GENERIC, USE_MEM_VM} USE_MEM = USE_MEM_VM @@ -20,19 +21,19 @@ USE_MEM = USE_MEM_VM # Debugging Flags # Strips out calls to assert() -CFLAGS += -DNDEBUG +# CFLAGS += -DNDEBUG # Turns on debuglog and other assorted printfs in third party libs -# CFLAGS += -DDEBUG +CFLAGS += -DDEBUG # Redirects debuglogs to /runtime/bin/awesome.log #FIXME This log should be changed to sledge.log (and likely to a user defined path) # CFLAGS += -DLOG_TO_FILE # Various Informational Logs for Debugging -# CFLAGS += -DLOG_STATE_CHANGES +CFLAGS += -DLOG_STATE_CHANGES # CFLAGS += -DLOG_LOCK_OVERHEAD -# CFLAGS += -DLOG_CONTEXT_SWITCHES +CFLAGS += -DLOG_CONTEXT_SWITCHES # CFLAGS += -DLOG_ADMISSIONS_CONTROL # CFLAGS += -DLOG_SANDBOX_PERF # CFLAGS += -DLOG_REQUEST_ALLOCATION @@ -42,16 +43,19 @@ CFLAGS += -DNDEBUG # This flag dumps totals of incoming requests and outgoing responses, broken out by status code # family, such as 2XX, 4XX, 5XX. It is useful to debug clients hanging waiting for a response. # To log, run `call runtime_log_requests_responses()` while in GDB -# CFLAGS += -DLOG_TOTAL_REQS_RESPS +CFLAGS += -DLOG_TOTAL_REQS_RESPS # This flag logs the total number of sandboxes in the various states # It is useful to debug if sandboxes are "getting caught" in a particular state # To log, run `call runtime_log_sandbox_states()` while in GDB -# CFLAGS += -DLOG_SANDBOX_TOTALS +CFLAGS += -DLOG_SANDBOX_TOTALS # This flag enables an per-worker atomic count of sandbox's local runqueue count in thread local storage # Useful to debug if sandboxes are "getting caught" or "leaking" while in a local runqueue -# CFLAGS += -DLOG_LOCAL_RUNQUEUE +CFLAGS += -DLOG_LOCAL_RUNQUEUE + +# Debug the HTTP Parser +CFLAGS += -DLOG_HTTP_PARSER # System Configuraiton Flags diff --git a/runtime/include/libuv_callbacks.h b/runtime/include/libuv_callbacks.h index 1f96615..e05d9e8 100644 --- a/runtime/include/libuv_callbacks.h +++ b/runtime/include/libuv_callbacks.h @@ -25,6 +25,7 @@ libuv_callbacks_on_read_parse_http_request(uv_stream_t *stream, ssize_t number_r /* Parse the chunks libuv has read on our behalf until we've parse to message end */ if (number_read > 0) { + // FIXME: Broken by refactor to sandbox_parse_http_request changes to return code if (sandbox_parse_http_request(sandbox, number_read) != 0) return; sandbox->request_response_data_length += number_read; struct http_request *rh = &sandbox->http_request; diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index a8e1a0c..3db2ecd 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -99,6 +99,7 @@ struct sandbox { uv_tcp_t client_libuv_stream; uv_shutdown_t client_libuv_shutdown_request; + bool is_repeat_header; http_parser http_parser; struct http_request http_request; struct http_response http_response; @@ -137,7 +138,7 @@ struct sandbox *sandbox_allocate(struct sandbox_request *sandbox_request); void sandbox_free(struct sandbox *sandbox); void sandbox_free_linear_memory(struct sandbox *sandbox); void sandbox_main(struct sandbox *sandbox); -int sandbox_parse_http_request(struct sandbox *sandbox, size_t length); +size_t sandbox_parse_http_request(struct sandbox *sandbox, size_t length); static inline char * sandbox_state_stringify(sandbox_state_t state) diff --git a/runtime/src/current_sandbox.c b/runtime/src/current_sandbox.c index 5eb0497..6cf794a 100644 --- a/runtime/src/current_sandbox.c +++ b/runtime/src/current_sandbox.c @@ -54,7 +54,7 @@ current_sandbox_initialize_io_handle(void) return sandbox_initialize_io_handle(current_sandbox_get()); } -int sandbox_parse_http_request(struct sandbox *sandbox, size_t l); +size_t sandbox_parse_http_request(struct sandbox *sandbox, size_t l); /** * Sets the file descriptor of the sandbox's ith io_handle diff --git a/runtime/src/http_parser_settings.c b/runtime/src/http_parser_settings.c index eb59919..ff20787 100644 --- a/runtime/src/http_parser_settings.c +++ b/runtime/src/http_parser_settings.c @@ -24,8 +24,13 @@ int http_parser_settings_on_url(http_parser *parser, const char *at, size_t length) { struct sandbox *sandbox = (struct sandbox *)parser->data; + if (sandbox->http_request.message_end || sandbox->http_request.header_end) return 0; +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0); +#endif + return 0; } @@ -40,8 +45,14 @@ http_parser_settings_on_message_begin(http_parser *parser) struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; - http_request->message_begin = 1; - http_request->last_was_value = 1; /* should always start with a header */ + if (sandbox->http_request.message_end || sandbox->http_request.header_end) return 0; + +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif + + http_request->message_begin = true; + http_request->last_was_value = true; /* should always start with a header */ return 0; } @@ -60,14 +71,45 @@ http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; - if (http_request->last_was_value) http_request->header_count++; - assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); - assert(length < HTTP_MAX_HEADER_LENGTH); + if (sandbox->http_request.message_end || sandbox->http_request.header_end) return 0; - http_request->last_was_value = 0; +// idef parser debug +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif - /* it is from the sandbox's request_response_data, should persist. */ - http_request->headers[http_request->header_count - 1].key = (char *)at; + /* Previous name continues */ + if (http_request->last_was_value == false) { + assert(http_request->header_count > 0); + strncat(http_request->headers[http_request->header_count].key, at, length); + return 0; + } + + /* + * We receive repeat headers for an unknown reason, so we need to ignore repeat headers + * This probably means that the headers are getting reparsed, so for the sake of performance + * this should be fixed upstream + */ + + +#ifdef LOG_HTTP_PARSER + for (int i = 0; i < http_request->header_count; i++) { + if (strncmp(http_request->headers[i].key, at, length) == 0) { + debuglog("Repeat header!\n"); + assert(0); + sandbox->is_repeat_header = true; + break; + } + } +#endif + + if (!sandbox->is_repeat_header) { + if (unlikely(http_request->header_count <= HTTP_MAX_HEADER_COUNT)) { return -1; } + if (unlikely(length < HTTP_MAX_HEADER_LENGTH)) { return -1; } + http_request->headers[http_request->header_count++].key = (char *)at; + http_request->last_was_value = false; + sandbox->is_repeat_header = false; + } return 0; } @@ -86,13 +128,21 @@ http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; - http_request->last_was_value = 1; - assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); - assert(length < HTTP_MAX_HEADER_VALUE_LENGTH); + if (http_request->message_end || http_request->header_end) return 0; - /* it is from the sandbox's request_response_data, should persist. */ - http_request->headers[http_request->header_count - 1].value = (char *)at; +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif + + // TODO: If last_was_value is already true, we might need to append to value + + /* it is from the sandbox's request_response_data, should persist. */ + if (!sandbox->is_repeat_header) { + if (unlikely(length < HTTP_MAX_HEADER_VALUE_LENGTH)) { return -1; } + http_request->headers[http_request->header_count - 1].value = (char *)at; + http_request->last_was_value = true; + } return 0; } @@ -106,17 +156,23 @@ http_parser_settings_on_header_end(http_parser *parser) { struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; + if (http_request->message_end || http_request->header_end) return 0; + +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif - http_request->header_end = 1; + http_request->header_end = true; return 0; } /** * http-parser callback called for HTTP Bodies * Assigns the parsed data to the http_request body of the sandbox struct + * Presumably, this might only be part of the body * @param parser - * @param at - * @param length + * @param at - start address of body + * @param length - length of body * @returns 0 */ int @@ -125,13 +181,37 @@ http_parser_settings_on_body(http_parser *parser, const char *at, size_t length) struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; + if (http_request->message_end) return 0; + +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif + + /* Assumption: We should never exceed the buffer we're reusing */ assert(http_request->body_length + length <= sandbox->module->max_request_size); - if (!http_request->body) - http_request->body = (char *)at; - else - assert(http_request->body + http_request->body_length == at); - http_request->body_length += length; + + if (!http_request->body) { + /* If this is the first invocation of the callback, just set */ + http_request->body = (char *)at; + http_request->body_length = length; + } else { +#ifdef LOG_HTTP_PARSER + debuglog("Body: %p, Existing Length: %d\n", http_request->body, http_request->body_length); + + debuglog("Expected Offset %d, Actual Offset: %lu\n", http_request->body_length, + at - http_request->body); + + /* Attempt to copy and print the entire body */ + uint64_t possible_body_len = at - http_request->body; + char test_buffer[possible_body_len + length + 1]; + strncpy(test_buffer, http_request->body, possible_body_len); + test_buffer[length] = '\0'; + debuglog("http_parser_settings_on_body: len %lu, content: %s\n", possible_body_len, test_buffer); +#endif + + http_request->body_length += length; + } return 0; } @@ -147,7 +227,12 @@ http_parser_settings_on_msg_end(http_parser *parser) struct sandbox * sandbox = (struct sandbox *)parser->data; struct http_request *http_request = &sandbox->http_request; - http_request->message_end = 1; + if (http_request->message_end) return 0; +#ifdef LOG_HTTP_PARSER + debuglog("sandbox: %lu\n", sandbox->request_arrival_timestamp); +#endif + + http_request->message_end = true; return 0; } diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 37b978d..1d1d97f 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -47,34 +47,6 @@ sandbox_setup_arguments(struct sandbox *sandbox) stub_init(string_off); } -/** - * Run the http-parser on the next N bytes of the sandbox's request_response_data buffer - * Success means that a "chunk" was fully parsed, not that parsing of a full request is complete - * @param sandbox the sandbox containing that we want to parse - * @param length The size of the data that we want to parse - * @returns 0 on success, -1 on failure - */ -int -sandbox_parse_http_request(struct sandbox *sandbox, size_t length) -{ - assert(sandbox != NULL); - - if (length == 0) return 0; - - /* Assumption: We shouldn't have anything left to parse if message was successfully parsed to completion */ - if (unlikely(sandbox->http_request.message_end)) { - debuglog("Unexpectedly received client data after message was parsed to completion"); - }; - - size_t length_parsed = http_parser_execute(&sandbox->http_parser, http_parser_settings_get(), - sandbox->request_response_data - + sandbox->request_response_data_length, - length); - - if (length_parsed != length) return -1; - return 0; -} - /** * Receive and Parse the Request for the current sandbox * @return 0 if message parsing complete, -1 on error @@ -92,9 +64,14 @@ sandbox_receive_and_parse_client_request(struct sandbox *sandbox) while (!sandbox->http_request.message_end) { /* Read from the Socket */ - int length_read = recv(sandbox->client_socket_descriptor, - &sandbox->request_response_data[sandbox->request_response_data_length], - sandbox->module->max_request_size - sandbox->request_response_data_length, 0); + ssize_t length_read = recv(sandbox->client_socket_descriptor, + &sandbox->request_response_data[sandbox->request_response_data_length], + sandbox->module->max_request_size - sandbox->request_response_data_length, + 0); + + /* Unexpected client shutdown.. or is this just EOF */ + if (length_read == 0 && !sandbox->http_request.message_end) goto err; + if (length_read < 0) { if (errno == EAGAIN) { worker_thread_block_current_sandbox(); @@ -107,13 +84,35 @@ sandbox_receive_and_parse_client_request(struct sandbox *sandbox) } } + + if (sandbox->http_request.message_end) break; + +#ifdef LOG_HTTP_PARSER + debuglog("http_parser_execute(%p, %p, %p, %lu)", &sandbox->http_parser, http_parser_settings_get(), + &sandbox->request_response_data[sandbox->request_response_data_length], length_read); +#endif + + http_parser_execute(&sandbox->http_parser, http_parser_settings_get(), + &sandbox->request_response_data[sandbox->request_response_data_length], + length_read); + + /* Try to parse what we've read */ - if (sandbox_parse_http_request(sandbox, length_read) < 0) { + /* TODO: Consider 0 as EOF? */ + size_t length_parsed = + http_parser_execute(&sandbox->http_parser, http_parser_settings_get(), + &sandbox->request_response_data[sandbox->request_response_data_length], + length_read); + + // size_t length_parsed = sandbox_parse_http_request(sandbox, length_read); + if (length_parsed != length_read) { debuglog("Error parsing socket %d\n", sandbox->client_socket_descriptor); goto err; } - sandbox->request_response_data_length += length_read; + sandbox->request_response_data_length += length_parsed; + + debuglog("After Read: %lu", sandbox->request_response_data_length); } diff --git a/runtime/tests/mixed_preemption/debug.sh b/runtime/tests/mixed_preemption/debug.sh new file mode 100755 index 0000000..f3dfe65 --- /dev/null +++ b/runtime/tests/mixed_preemption/debug.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Executes the runtime in GDB +# Substitutes the absolute path from the container with a path relatively derived from the location of this script +# This allows debugging outside of the Docker container +# Also disables pagination and stopping on SIGUSR1 + +declare project_path="$( + cd "$(dirname "$1")/../.." + pwd +)" +echo $project_path +cd ../../bin +export LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH" +gdb --eval-command="handle SIGUSR1 nostop" \ + --eval-command="set pagination off" \ + --eval-command="set substitute-path /sledge/runtime $project_path" \ + --eval-command="run ../tests/mixed_preemption/test_mixed_preemption.json" \ + ./sledgert +cd ../../tests diff --git a/runtime/tests/mixed_preemption/demo.sh b/runtime/tests/mixed_preemption/demo.sh new file mode 100755 index 0000000..199cef7 --- /dev/null +++ b/runtime/tests/mixed_preemption/demo.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# cd ../../bin +# LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH" ./sledgert ../tests/mixed_preemption/test_mixed_preemption.json & +# cd ../tests/mixed_preemption/ + +# TODO: Run small samples on each port to let the runtime figure out the execution time +# ab -s 999999999 -v 4 -n 50 -c 1 -r -p ./req/fib10.txt localhost:10010/ +# ab -s 999999999 -v 4 -n 50 -c 1 -r -p ./req/fib20.txt localhost:10020/ +# ab -s 999999999 -v 4 -n 50 -c 1 -r -p ./req/fib25.txt localhost:10025/ +# ab -s 999999999 -v 4 -n 50 -c 1 -r -p ./req/fib30.txt localhost:10030/ +# ab -s 999999999 -v 4 -n 50 -c 1 -r -p ./req/fib35.txt localhost:10035/ +wrk -d 10s -t1 -s post.lua http://localhost:10010 -- 2 10\n >/dev/null +# wrk -d 10s -t1 -s post.lua http://localhost:10030 -- 2 30\n >/dev/null +# wrk -d 1m -t1 -s post.lua http://localhost:10020 -- 2 20\n + +# fib(10) +# sleep 2 +# wrk -d 1m -t1 -s post.lua http://localhost:10010 -- 20 10\n >./res/fib10.txt +# wrk -d 1m -t1 -s post.lua http://localhost:10020 -- 2 20\n >./res/fib20.txt & +# wrk -d 1m -t1 -s post.lua http://localhost:10025 -- 2 25\n >./res/fib25.txt & +# wrk -d 1m -t1 -s post.lua http://localhost:10030 -- 2 30\n >./res/fib30.txt +# wrk -d 1m -t1 -s post.lua http://localhost:10035 -- 2 35\n +# ab -n 10000 -c 1 -r -p ./req/fib10.txt localhost:10000/ >./res/fib10.txt & +# ab -n 10000 -c 1 -r -p ./req/fib20.txt localhost:10001/ >./res/fib20.txt & +# ab -n 10000 -c 1 -r -p ./req/fib25.txt localhost:10002/ >./res/fib25.txt & +# ab -n 10000 -c 1 -r -p ./req/fib30.txt localhost:10030/ >./res/fib30.txt & +# ab -n 10000 -c 1 -r -p ./req/fib35.txt localhost:10035/ >./res/fib35.txt + +# Kill the Background Sledge processes +# ps -e -o pid,cmd | grep sledgert | grep json | cut -d\ -f 1 | xargs kill +# pkill sledgert +# pkill ab +# pkill wrk diff --git a/runtime/tests/mixed_preemption/post.lua b/runtime/tests/mixed_preemption/post.lua new file mode 100644 index 0000000..ca74290 --- /dev/null +++ b/runtime/tests/mixed_preemption/post.lua @@ -0,0 +1,43 @@ +-- Default to 1 request / second +wrk.method = "POST" +wrk.body = "10\n" +wrk.headers["Content-Type"] = "text/plain" +local delay_val = 1000 + +function init(args) + if #args >= 1 then + -- First argument is "requests per second" per thread + delay_val = (1000 / args[1]) + end + + if #args >= 2 then + -- Second argument is argument + wrk.body = args[2] + end +end + +-- Uncomment to dynamically generate a different request each time +-- function request() +-- return wrk.format(nil, nil, nil,tostring(math.random(10, 23)) .."\n") +-- end + +-- Wrk calls a function name delay to get the delay between requests (in ms) +function delay() + return delay_val +end + +function response(status, headers, body) + io.write(string.format("%s: %s\n", status, body)) +end + +-- Done Phase + +-- Called when complete, presenting aggregate results +function done(summary, latency, requests) + for i = 1, 99 do + io.write(string.format("%d %d\n", i, latency:percentile(i))) + end +end + + + diff --git a/runtime/tests/mixed_preemption/res/fib10.txt b/runtime/tests/mixed_preemption/res/fib10.txt new file mode 100644 index 0000000..97b9930 --- /dev/null +++ b/runtime/tests/mixed_preemption/res/fib10.txt @@ -0,0 +1,107 @@ +Running 1m test @ http://localhost:10010 + 1 threads and 10 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 0.00us 0.00us 0.00us -nan% + Req/Sec 0.00 0.00 0.00 -nan% + 0 requests in 1.00m, 0.00B read +Requests/sec: 0.00 +Transfer/sec: 0.00B +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +10 0 +11 0 +12 0 +13 0 +14 0 +15 0 +16 0 +17 0 +18 0 +19 0 +20 0 +21 0 +22 0 +23 0 +24 0 +25 0 +26 0 +27 0 +28 0 +29 0 +30 0 +31 0 +32 0 +33 0 +34 0 +35 0 +36 0 +37 0 +38 0 +39 0 +40 0 +41 0 +42 0 +43 0 +44 0 +45 0 +46 0 +47 0 +48 0 +49 0 +50 0 +51 0 +52 0 +53 0 +54 0 +55 0 +56 0 +57 0 +58 0 +59 0 +60 0 +61 0 +62 0 +63 0 +64 0 +65 0 +66 0 +67 0 +68 0 +69 0 +70 0 +71 0 +72 0 +73 0 +74 0 +75 0 +76 0 +77 0 +78 0 +79 0 +80 0 +81 0 +82 0 +83 0 +84 0 +85 0 +86 0 +87 0 +88 0 +89 0 +90 0 +91 0 +92 0 +93 0 +94 0 +95 0 +96 0 +97 0 +98 0 +99 0 diff --git a/runtime/tests/mixed_preemption/test_mixed_preemption.json b/runtime/tests/mixed_preemption/test_mixed_preemption.json new file mode 100644 index 0000000..cbd3b0c --- /dev/null +++ b/runtime/tests/mixed_preemption/test_mixed_preemption.json @@ -0,0 +1,70 @@ +{ + "active": "yes", + "name": "fibonacci_10", + "path": "fibonacci_wasm.so", + "port": 10010, + "relative-deadline-us": 4000, + "argsize": 1, + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1024, + "http-resp-headers": [], + "http-resp-size": 1024, + "http-resp-content-type": "text/plain" +}, +{ + "active": "yes", + "name": "fibonacci_20", + "path": "fibonacci_wasm.so", + "port": 10020, + "relative-deadline-us": 5000, + "argsize": 1, + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1024, + "http-resp-headers": [], + "http-resp-size": 1024, + "http-resp-content-type": "text/plain" +}, +{ + "active": "yes", + "name": "fibonacci_25", + "path": "fibonacci_wasm.so", + "port": 10025, + "relative-deadline-us": 6000, + "argsize": 1, + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1024, + "http-resp-headers": [], + "http-resp-size": 1024, + "http-resp-content-type": "text/plain" +}, +{ + "active": "yes", + "name": "fibonacci_30", + "path": "fibonacci_wasm.so", + "port": 10030, + "relative-deadline-us": 8000, + "argsize": 1, + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1024, + "http-resp-headers": [], + "http-resp-size": 1024, + "http-resp-content-type": "text/plain" +}, +{ + "active": "yes", + "name": "fibonacci_35", + "path": "fibonacci_wasm.so", + "port": 10035, + "relative-deadline-us": 53000, + "argsize": 1, + "http-req-headers": [], + "http-req-content-type": "text/plain", + "http-req-size": 1024, + "http-resp-headers": [], + "http-resp-size": 1024, + "http-resp-content-type": "text/plain" +}