feature: added SJF scheduler and Regression based prediction (#385)

* feature: added SJF scheduler
added REGRESSION based prediction support

* fix: error handling

* fixed the default values for def.server when not given

* fix: replace GET by POST for hey requests (fix by Xioasu)

* - update .clang-format props to match composite (almost)
- reformat C codes in the repo
- refactor the format.sh script
- fetch latest AWSM master

* Addressed Gabe's comments

* error handling for when model_scale and model_beta2 is zero

* fix the multi-tenantcy-predictions run.sh script

* - upgraded to LLVM_VERSION=13 both on sledge & AWSM
- updated dockerfile, main.yaml
- added new uninstall_llvm.sh script to ease LLVM removal
master
Emil 11 months ago committed by GitHub
parent 4ae8b02413
commit 6b0ba99e86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,4 +1,3 @@
---
BasedOnStyle: Mozilla
IndentWidth: 8
Language: Cpp
@ -10,10 +9,10 @@ AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: true
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: AllDefinitions
@ -38,7 +37,7 @@ BreakBeforeBinaryOperators: NonAssignment
ColumnLimit: 120
Cpp11BracedListStyle: false
Cpp11BracedListStyle: true
IndentCaseLabels: false
IndentWrappedFunctionNames: false
@ -47,10 +46,9 @@ KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2
DerivePointerAlignment: false
PointerAlignment: Right
SortIncludes: false
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true

@ -4,7 +4,7 @@ on: [push, pull_request]
env:
LLVM_VERSION: 13
WASI_SDK_URL: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
WASI_SDK_VERSION: 12
WASI_SDK_PATH: /opt/wasi-sdk
LANG: C.UTF-8
LANGUAGE: C.UTF-8
@ -18,10 +18,10 @@ jobs:
- name: Apt Update
run: sudo apt-get update
- uses: actions/checkout@v2
- name: Install LLVM
- name: Install Clang Format
run: |
sudo ./install_llvm.sh $LLVM_VERSION
- name: Clang Format
- name: Run Clang Format
run: ./format.sh -d
test:
runs-on: ubuntu-20.04
@ -62,6 +62,7 @@ jobs:
echo "/root/.cargo/bin:$PATH" >> $GITHUB_PATH
- name: Get wasi-sdk
run: |
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk-$WASI_SDK_VERSION.0-linux.tar.gz
wget $WASI_SDK_URL -O wasi-sdk.tar.gz
mkdir -p $WASI_SDK_PATH
tar xvfz wasi-sdk.tar.gz --strip-components=1 -C $WASI_SDK_PATH

@ -116,7 +116,7 @@
"tenant.h": "c",
"route_config.h": "c",
"http_router.h": "c",
"admissions_info.h": "c",
"execution_histogram.h": "c",
"tcp_server.h": "c",
"stdint.h": "c",
"scheduler_options.h": "c",
@ -144,7 +144,20 @@
"algorithm": "c",
"stdio.h": "c",
"get_time.h": "c",
"unistd.h": "c"
"unistd.h": "c",
"wasi.h": "c",
"stat.h": "c",
"functional": "c",
"sandbox_state.h": "c",
"ratio": "c",
"tuple": "c",
"type_traits": "c",
"perf_window.h": "c",
"http_route_total.h": "c",
"sledge_abi_symbols.h": "c",
"mutex": "c",
"lock.h": "c",
"route_latency.h": "c"
},
"files.exclude": {
"**/.git": true,

@ -1,9 +1,12 @@
# using ubuntu 20 docker image
FROM ubuntu:focal
ENV LLVM_VERSION=13
ENV WASI_SDK_VERSION=12
ARG DEBIAN_FRONTEND=noninteractive
ARG HEY_URL=https://hey-release.s3.us-east-2.amazonaws.com/hey_linux_amd64
ARG WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk_12.0_amd64.deb
ARG WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
ARG SHFMT_URL=https://github.com/mvdan/sh/releases/download/v3.2.4/shfmt_v3.2.4_linux_amd64
ARG SHELLCHECK_URL=https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz
@ -74,12 +77,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
vim \
wabt
ENV LLVM_VERSION=12
ADD install_llvm.sh /sledge/install_llvm.sh
RUN ./sledge/install_llvm.sh $LLVM_VERSION
# WASI-SDK
RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_12.0_amd64.deb && rm -f wasi-sdk_12.0_amd64.deb
RUN curl -sS -L -O $WASI_SDK_URL && dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
ENV WASI_SDK_PATH=/opt/wasi-sdk
# Create non-root user and add to sudoers

@ -27,15 +27,11 @@ all: \
license_plate_detection.install \
resize_image.install \
cnn_face_detection.install \
scratch_storage_get.install \
scratch_storage_set.install \
scratch_storage_delete.install \
scratch_storage_upsert.install \
get_jpeg_resolution.install \
.PHONY: clean
clean:
@make -C wasm_apps clean
@make -C scratch_storage clean
@rm -rf dist
@rm -rf ../runtime/bin/*.so
@ -69,7 +65,7 @@ dist/%.bc: ./wasm_apps/dist/%.wasm dist
${AWSMCC} ${AWSMFLAGS} $< -o $@
dist/%.ll: dist/%.bc
llvm-dis-12 $< -o $@
llvm-dis $< -o $@
dist/%.wasm.so: dist/%.bc
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@
@ -109,6 +105,9 @@ license_plate_detection.install: ../runtime/bin/license_plate_detection.wasm.so
.PHONY: cnn_face_detection.install
cnn_face_detection.install: ../runtime/bin/cnn_face_detection.wasm.so
.PHONY: get_jpeg_resolution.install
get_jpeg_resolution.install: ../runtime/bin/get_jpeg_resolution.wasm.so
.PHONY: trap_divzero.install
trap_divzero.install: ../runtime/bin/trap_divzero.wasm.so

@ -1 +1 @@
Subproject commit e2ba697861201f2aaca37460842ab5c34c8d1716
Subproject commit e3abafa1e18b6d600fc0ca7e0810fea1f6621ea6

@ -1,7 +1,9 @@
#!/bin/bash
LLVM_VERSION=13
validate() {
utility="clang-format-13"
utility="clang-format"
utility_version="$("$utility" --version 2> /dev/null)" || {
echo "$utility not found in path!"
exit 1
@ -11,7 +13,7 @@ validate() {
declare -i major=0
declare -i minor=0
declare -i patch=0
declare -i required_major=13
declare -i required_major=$LLVM_VERSION
declare -i required_minor=0
declare -i required_patch=0
@ -43,14 +45,14 @@ help() {
dry_run() {
find runtime \
\( -path "runtime/thirdparty" -o -path "applications/gocr" -o -path "applications/TinyEKF" -o -path "applications/CMSIS_5_NN" -o -path "applications/sod" -o -path "applications/**/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print \
| xargs clang-format -Werror -n -ferror-limit=0
\( -path "runtime/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print0 \
| xargs --null clang-format -Werror -n -ferror-limit=1
}
format() {
find runtime \
\( -path "runtime/thirdparty" -o -path "applications/gocr" -o -path "applications/TinyEKF" -o -path "applications/CMSIS_5_NN" -o -path "applications/sod" -o -path "applications/**/thirdparty" \) -prune -false -o \
\( -path "runtime/thirdparty" \) -prune -false -o \
-type f \( -iname \*.h -o -iname \*.c -o -iname \*.s \) -print0 \
| xargs --null clang-format -i
}

@ -1,12 +1,14 @@
#!/bin/bash
LLVM_VERSION=12
# Note, wasi-sdk versions do NOT match llvm versions, e.g. wasi-sdk-12 actually uses llvm-11
LLVM_VERSION=13
WASI_SDK_VERSION=12
ARCH=$(uname -m)
if [[ $ARCH = "x86_64" ]]; then
SHFMT_URL=https://github.com/mvdan/sh/releases/download/v3.4.3/shfmt_v3.4.3_linux_amd64
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk_12.0_amd64.deb
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-$WASI_SDK_VERSION/wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
elif [[ $ARCH = "aarch64" ]]; then
SHFMT_URL=https://github.com/patrickvane/shfmt/releases/download/master/shfmt_linux_arm
echo "ARM64 support is still a work in progress!"
@ -64,7 +66,7 @@ wget $SHFMT_URL -O shfmt && chmod +x shfmt && sudo mv shfmt /usr/local/bin/shfmt
sudo ./install_llvm.sh $LLVM_VERSION
curl -sS -L -O $WASI_SDK_URL && sudo dpkg -i wasi-sdk_12.0_amd64.deb && rm -f wasi-sdk_12.0_amd64.deb
curl -sS -L -O $WASI_SDK_URL && sudo dpkg -i wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb && rm -f wasi-sdk_$WASI_SDK_VERSION.0_amd64.deb
if [ -z "${WASI_SDK_PATH}" ]; then
export WASI_SDK_PATH=/opt/wasi-sdk

@ -8,28 +8,28 @@ echo "Installing LLVM $LLVM_VERSION"
# Script Installs clang, lldb, lld, and clangd
curl --proto '=https' --tlsv1.2 -sSf https://apt.llvm.org/llvm.sh | bash -s -- "$LLVM_VERSION"
# Installing "libc++-xx-dev" automagically installs "libc++1-xx", "libunwind-xx" and "libunwind-xx-dev"
apt-get install -y --no-install-recommends \
"libc++-$LLVM_VERSION-dev" \
"libc++abi-$LLVM_VERSION-dev" \
"libc++1-$LLVM_VERSION" \
"libunwind-$LLVM_VERSION" \
"libunwind-$LLVM_VERSION-dev" \
"clang-tools-$LLVM_VERSION" \
"clang-tidy-$LLVM_VERSION" \
"clang-format-$LLVM_VERSION"
sudo update-alternatives --remove-all clang-format
sudo update-alternatives --remove-all clang
sudo update-alternatives --remove-all clang++
sudo update-alternatives --remove-all llvm-config
sudo update-alternatives --remove-all llvm-objdump
sudo update-alternatives --remove-all llvm-objdump
sudo update-alternatives --remove-all clang-tidy
update-alternatives --remove-all wasm-ld
update-alternatives --remove-all llvm-config
update-alternatives --remove-all llvm-objdump
update-alternatives --remove-all llvm-dis
update-alternatives --remove-all clang-format
update-alternatives --remove-all clang
update-alternatives --remove-all clang++
update-alternatives --remove-all clang-tidy
update-alternatives --install /usr/bin/wasm-ld wasm-ld "/usr/bin/wasm-ld-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-config llvm-config "/usr/bin/llvm-config-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-objdump llvm-objdump "/usr/bin/llvm-objdump-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION 100
update-alternatives --install /usr/bin/clang-format clang-format "/usr/bin/clang-format-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang clang "/usr/bin/clang-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang++ clang++ "/usr/bin/clang++-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-config llvm-config "/usr/bin/llvm-config-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/llvm-objdump llvm-objdump "/usr/bin/llvm-objdump-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/clang-tidy clang-tidy "/usr/bin/clang-tidy-$LLVM_VERSION" 100
update-alternatives --install /usr/bin/wasm-ld wasm-ld "/usr/bin/wasm-ld-$LLVM_VERSION" 100

@ -38,6 +38,10 @@ BINARY_NAME=sledgert
# Feature Toggles
CFLAGS += -DEXECUTION_HISTOGRAM
# CFLAGS += -DEXECUTION_REGRESSION
# It is recommended (not mandatory) to enable this flag along with the EXECUTION_HISTOGRAM flag:
# CFLAGS += -DADMISSIONS_CONTROL
# Debugging Flags
@ -56,6 +60,7 @@ BINARY_NAME=sledgert
# CFLAGS += -DLOG_TO_FILE
# Various Informational Logs for Debugging
# CFLAGS += -DLOG_EXECUTION_HISTOGRAM
# CFLAGS += -DLOG_ADMISSIONS_CONTROL
# CFLAGS += -DLOG_CONTEXT_SWITCHES
# CFLAGS += -DLOG_HTTP_PARSER

@ -1,18 +1,19 @@
#pragma once
#ifdef ADMISSIONS_CONTROL
#include <stdbool.h>
#include <stdint.h>
#ifdef ADMISSIONS_CONTROL
#define ADMISSIONS_CONTROL_GRANULARITY 1000000
extern _Atomic uint64_t admissions_control_admitted;
extern uint64_t admissions_control_capacity;
#endif
void admissions_control_initialize(void);
void admissions_control_add(uint64_t admissions_estimate);
void admissions_control_subtract(uint64_t admissions_estimate);
uint64_t admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline);
uint64_t admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us);
void admissions_control_log_decision(uint64_t admissions_estimate, bool admitted);
uint64_t admissions_control_decide(uint64_t admissions_estimate);
#endif

@ -1,15 +0,0 @@
#pragma once
#include "perf_window_t.h"
struct admissions_info {
struct perf_window perf_window;
uint8_t percentile; /* 50 - 99 */
int control_index; /* Precomputed Lookup index when perf_window is full */
uint64_t estimate; /* cycles */
uint64_t relative_deadline; /* Relative deadline in cycles. This is duplicated state */
};
void admissions_info_initialize(struct admissions_info *admissions_info, uint8_t percentile,
uint64_t expected_execution, uint64_t relative_deadline);
void admissions_info_update(struct admissions_info *admissions_info, uint64_t execution_duration);

@ -3,9 +3,9 @@
#include <setjmp.h>
#include <ucontext.h>
#include "arch/arch_context_variant_t.h"
#include "arch/reg_t.h"
#include "arch/ureg_t.h"
#include "arch/arch_context_variant_t.h"
struct arch_context {
arch_context_variant_t variant;

@ -1,5 +1,6 @@
#pragma once
#include "likely.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

@ -3,6 +3,7 @@
#include <threads.h>
#include "current_wasm_module_instance.h"
#include "listener_thread.h"
#include "sandbox_types.h"
/* current sandbox that is active.. */
@ -30,24 +31,25 @@ current_sandbox_set(struct sandbox *sandbox)
/* Unpack hierarchy to avoid pointer chasing */
if (sandbox == NULL) {
sledge_abi__current_wasm_module_instance = (struct wasm_module_instance){
/* Public */
.abi =
(struct sledge_abi__wasm_module_instance){
.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.capacity = 0,
.max = 0,
.buffer = NULL,
},
.table = NULL,
.wasmg_0 = 0,
},
/* Private */
.wasi_context = NULL,
/* Public */
.abi =
(struct sledge_abi__wasm_module_instance){
.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.capacity = 0,
.max = 0,
.buffer = NULL,
},
.table = NULL,
.wasmg_0 = 0,
},
/* Private */
.wasi_context = NULL,
};
worker_thread_current_sandbox = NULL;
runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX;
worker_thread_current_sandbox = NULL;
/* This is because the event core does not maintain core-assigned deadline */
if (!listener_thread_is_running()) runtime_worker_threads_deadline[worker_thread_idx] = UINT64_MAX;
} else {
sledge_abi__current_wasm_module_instance.wasi_context = sandbox->wasi_context;
memcpy(&sledge_abi__current_wasm_module_instance.abi.memory, &sandbox->memory->abi,
@ -55,8 +57,9 @@ current_sandbox_set(struct sandbox *sandbox)
sledge_abi__current_wasm_module_instance.abi.table = sandbox->module->indirect_table;
wasm_globals_update_if_used(&sandbox->globals, 0,
&sledge_abi__current_wasm_module_instance.abi.wasmg_0);
worker_thread_current_sandbox = sandbox;
runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline;
worker_thread_current_sandbox = sandbox;
if (!listener_thread_is_running())
runtime_worker_threads_deadline[worker_thread_idx] = sandbox->absolute_deadline;
}
}

@ -0,0 +1,14 @@
#pragma once
#include "perf_window_t.h"
struct execution_histogram {
struct perf_window perf_window;
uint8_t percentile; /* 50 - 99 */
int control_index; /* Precomputed Lookup index when perf_window is full */
uint64_t estimated_execution; /* cycles */
};
void execution_histogram_initialize(struct execution_histogram *execution_histogram, uint8_t percentile,
uint64_t expected_execution);
void execution_histogram_update(struct execution_histogram *execution_histogram, uint64_t execution_duration);

@ -0,0 +1,26 @@
#pragma once
#ifdef EXECUTION_REGRESSION
#include "http_session.h"
#include <stdint.h>
static inline uint64_t
get_regression_prediction(struct http_session *session)
{
/* Default Pre-processing - Extract payload size */
const int payload_size = session->http_request.body_length;
const double regression_params[2] = {payload_size, session->paregression_paramram2};
/* Perform Linear Regression using the factors provided by the regressor performed AoT on Matlab using training
* tenant-given dataset */
const struct regression_model model = session->route->regr_model;
const uint64_t prediction = (regression_params[0] / model.scale * model.beta1
+ regression_params[1] / model.scale * model.beta2)
+ model.bias;
return prediction;
}
#endif

@ -1,14 +1,12 @@
#pragma once
#include <stdlib.h>
#include <string.h>
#include "http.h"
#include "module.h"
#include "route_latency.h"
#include "route.h"
#include "route_config.h"
#include "route_latency.h"
#include "vec.h"
#include <stdlib.h>
typedef struct route route_t;
VEC(route_t)
@ -22,7 +20,8 @@ http_router_init(http_router_t *router, size_t capacity)
}
static inline int
http_router_add_route(http_router_t *router, struct route_config *config, struct module *module)
http_router_add_route(http_router_t *router, struct route_config *config, struct module *module,
struct module *module_proprocess)
{
assert(router != NULL);
assert(config != NULL);
@ -30,20 +29,35 @@ http_router_add_route(http_router_t *router, struct route_config *config, struct
assert(config->route != NULL);
assert(config->http_resp_content_type != NULL);
struct route route = { .route = config->route,
.module = module,
.relative_deadline_us = config->relative_deadline_us,
.relative_deadline = (uint64_t)config->relative_deadline_us
* runtime_processor_speed_MHz,
.response_content_type = config->http_resp_content_type };
struct route route = {.route = config->route,
.module = module,
.relative_deadline_us = config->relative_deadline_us,
.relative_deadline = (uint64_t)config->relative_deadline_us * runtime_processor_speed_MHz,
.response_content_type = config->http_resp_content_type};
route_latency_init(&route.latency);
http_route_total_init(&route.metrics);
/* Admissions Control */
uint64_t expected_execution = (uint64_t)config->expected_execution_us * runtime_processor_speed_MHz;
admissions_info_initialize(&route.admissions_info, config->admissions_percentile, expected_execution,
route.relative_deadline);
#ifdef EXECUTION_REGRESSION
/* Execution Regression setup */
route.module_proprocess = module_proprocess;
route.regr_model.bias = config->model_bias / 1000.0;
route.regr_model.scale = config->model_scale / 1000.0;
route.regr_model.num_of_param = config->model_num_of_param;
route.regr_model.beta1 = config->model_beta1 / 1000.0;
route.regr_model.beta2 = config->model_beta2 / 1000.0;
#endif
const uint64_t expected_execution = route.relative_deadline / 2;
#ifdef ADMISSIONS_CONTROL
/* Addmissions Control setup */
route.execution_histogram.estimated_execution = expected_execution;
#endif
#ifdef EXECUTION_HISTOGRAM
/* Execution Histogram setup */
execution_histogram_initialize(&route.execution_histogram, config->admissions_percentile, expected_execution);
#endif
int rc = vec_route_t_push(router, route);
if (unlikely(rc == -1)) { return -1; }

@ -57,6 +57,9 @@ struct http_session {
uint64_t request_downloaded_timestamp;
uint64_t response_takeoff_timestamp;
uint64_t response_sent_timestamp;
bool did_preprocessing;
uint64_t preprocessing_duration;
double regression_param; /* Calculated in tenant preprocessing logic if provided */
};
extern void http_session_perf_log_print_entry(struct http_session *http_session);

@ -1,8 +1,8 @@
#pragma once
#include "http_session.h"
#include "pretty_print.h"
#include "runtime.h"
#include "http_session.h"
extern FILE *http_session_perf_log;
typedef struct http_session http_session;
@ -15,8 +15,8 @@ static inline void
http_session_perf_log_print_header()
{
if (http_session_perf_log == NULL) { perror("http_session perf log"); }
fprintf(http_session_perf_log,
"tenant,route,state,header_len,resp_body_len,receive_duration,sent_duration,total_lifetime,proc_MHz\n");
fprintf(http_session_perf_log, "tenant,route,state,header_len,resp_body_len,receive_duration,sent_duration,"
"total_lifetime,preprocessing,proc_MHz\n");
}
static inline void

@ -2,12 +2,12 @@
#include <errno.h>
#include <inttypes.h>
#include <jsmn.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jsmn.h>
static inline char *
jsmn_type(jsmntype_t type)

@ -98,12 +98,12 @@ map_set(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint32_
}
struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){ .hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head };
*(new_node) = (struct map_node){.hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head};
// Copy Key and Value
memcpy(new_node->key, key, key_len);
@ -174,12 +174,12 @@ map_upsert(struct map *map, uint8_t *key, uint32_t key_len, uint8_t *value, uint
struct map_node *new_node = (struct map_node *)xmalloc(sizeof(struct map_node));
*(new_node) = (struct map_node){ .hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head };
*(new_node) = (struct map_node){.hash = hash,
.key = xmalloc(key_len),
.key_len = key_len,
.value = xmalloc(value_len),
.value_len = value_len,
.next = bucket->head};
assert(new_node->key);
assert(new_node->value);

@ -1,22 +1,11 @@
#pragma once
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include "admissions_control.h"
#include "admissions_info.h"
#include "current_wasm_module_instance.h"
#include "panic.h"
#include "pool.h"
#include "sledge_abi_symbols.h"
#include "tcp_server.h"
#include "types.h"
#include "sledge_abi_symbols.h"
#include "wasm_stack.h"
#include "wasm_memory.h"
#include "wasm_table.h"
#include "wasm_stack.h"
extern thread_local int worker_thread_idx;
@ -28,9 +17,15 @@ struct module_pool {
struct wasm_stack_pool stack;
} CACHE_PAD_ALIGNED;
enum module_type
{
APP_MODULE,
PREPROCESS_MODULE
};
struct module {
char *path;
uint32_t stack_size; /* a specification? */
char *path;
uint32_t stack_size; /* a specification? */
enum module_type type;
/* Handle and ABI Symbols for *.so file */
struct sledge_abi_symbols abi;
@ -41,12 +36,13 @@ struct module {
struct module_pool *pools;
} CACHE_PAD_ALIGNED;
/********************************
* Public Methods from module.c *
*******************************/
void module_free(struct module *module);
struct module *module_alloc(char *path);
struct module *module_alloc(char *path, enum module_type type);
/*************************
* Public Static Inlines *
@ -115,7 +111,9 @@ module_alloc_table(struct module *module)
static inline void
module_initialize_pools(struct module *module)
{
for (int i = 0; i < runtime_worker_threads_count; i++) {
/* Create only a single pool for the preprocessing module, since it is executed only by the event core. */
const int n = module->type == APP_MODULE ? runtime_worker_threads_count : 1;
for (int i = 0; i < n; i++) {
wasm_memory_pool_init(&module->pools[i].memory, false);
wasm_stack_pool_init(&module->pools[i].stack, false);
}
@ -124,7 +122,8 @@ module_initialize_pools(struct module *module)
static inline void
module_deinitialize_pools(struct module *module)
{
for (int i = 0; i < runtime_worker_threads_count; i++) {
const int n = module->type == APP_MODULE ? runtime_worker_threads_count : 1;
for (int i = 0; i < n; i++) {
wasm_memory_pool_deinit(&module->pools[i].memory);
wasm_stack_pool_deinit(&module->pools[i].stack);
}

@ -72,8 +72,8 @@ perf_window_fill(struct perf_window *perf_window, uint64_t newest_execution_time
{
for (uint16_t i = 0; i < PERF_WINDOW_CAPACITY; i++) {
perf_window->by_termination[i] = i;
perf_window->by_duration[i] = (struct execution_node){ .execution_time = newest_execution_time,
.by_termination_idx = i };
perf_window->by_duration[i] = (struct execution_node){.execution_time = newest_execution_time,
.by_termination_idx = i};
}
perf_window->count = PERF_WINDOW_CAPACITY;
}

@ -1,7 +1,7 @@
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include <stdio.h>
#define PRETTY_PRINT_COLOR_CODE_RED "\033[1;31m"
#define PRETTY_COLOR_CODE_GREEN "\033[0;32m"

@ -3,8 +3,8 @@
#include <errno.h>
#include "lock.h"
#include "listener_thread.h"
#include "lock.h"
#include "panic.h"
#include "runtime.h"
#include "worker_thread.h"

@ -2,8 +2,8 @@
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "runtime.h" /* For runtime_pid */

@ -1,22 +1,32 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include "admissions_info.h"
#include "module.h"
#include "execution_histogram.h"
#include "http_route_total.h"
#include "module.h"
#include "perf_window.h"
struct regression_model {
double bias;
double scale;
uint32_t num_of_param;
double beta1;
double beta2;
};
/* Assumption: entrypoint is always _start. This should be enhanced later */
struct route {
char *route;
struct http_route_total metrics;
struct module *module;
/* HTTP State */
uint32_t relative_deadline_us;
uint64_t relative_deadline; /* cycles */
char *response_content_type;
struct admissions_info admissions_info;
struct perf_window latency;
uint32_t relative_deadline_us;
uint64_t relative_deadline; /* cycles */
char *response_content_type;
struct execution_histogram execution_histogram;
struct perf_window latency;
struct module *module_proprocess;
struct regression_model regr_model;
};

@ -13,8 +13,13 @@ enum route_config_member
route_config_member_route,
route_config_member_path,
route_config_member_admissions_percentile,
route_config_member_expected_execution_us,
route_config_member_relative_deadline_us,
route_config_member_path_preprocess,
route_config_member_model_bias,
route_config_member_model_scale,
route_config_member_model_num_of_param,
route_config_member_model_beta1,
route_config_member_model_beta2,
route_config_member_http_resp_content_type,
route_config_member_len
};
@ -23,8 +28,13 @@ struct route_config {
char *route;
char *path;
uint8_t admissions_percentile;
uint32_t expected_execution_us;
uint32_t relative_deadline_us;
char *path_preprocess;
uint32_t model_bias;
uint32_t model_scale;
uint32_t model_num_of_param;
uint32_t model_beta1;
uint32_t model_beta2;
char *http_resp_content_type;
};
@ -45,9 +55,15 @@ route_config_print(struct route_config *config)
printf("[Route] Route: %s\n", config->route);
printf("[Route] Path: %s\n", config->path);
printf("[Route] Admissions Percentile: %hhu\n", config->admissions_percentile);
printf("[Route] Expected Execution (us): %u\n", config->expected_execution_us);
printf("[Route] Relative Deadline (us): %u\n", config->relative_deadline_us);
printf("[Route] HTTP Response Content Type: %s\n", config->http_resp_content_type);
#ifdef EXECUTION_HISTOGRAM
printf("[Route] Path of Preprocessing Module: %s\n", config->path_preprocess);
printf("[Route] Model Bias: %u\n", config->model_bias);
printf("[Route] Model Scale: %u\n", config->model_scale);
printf("[Route] Model Num of Parameters: %u\n", config->model_num_of_param);
printf("[Route] Model Betas: [%u, %u]\n", config->model_beta1, config->model_beta2);
#endif
}
/**
@ -59,7 +75,7 @@ static inline int
route_config_validate(struct route_config *config, bool *did_set)
{
if (did_set[route_config_member_route] == false) {
fprintf(stderr, "path field is required\n");
fprintf(stderr, "route field is required\n");
return -1;
}
@ -73,9 +89,9 @@ route_config_validate(struct route_config *config, bool *did_set)
config->http_resp_content_type = "text/plain";
}
if (scheduler != SCHEDULER_FIFO) {
if (scheduler != SCHEDULER_FIFO && scheduler != SCHEDULER_SJF) {
if (did_set[route_config_member_relative_deadline_us] == false) {
fprintf(stderr, "relative_deadline_us is required\n");
fprintf(stderr, "relative_deadline_us is required for the selected scheduler\n");
return -1;
}
@ -84,36 +100,80 @@ route_config_validate(struct route_config *config, bool *did_set)
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, config->relative_deadline_us);
return -1;
}
}
#ifdef ADMISSIONS_CONTROL
if (did_set[route_config_member_expected_execution_us] == false) {
fprintf(stderr, "expected-execution-us is required\n");
return -1;
}
#ifdef EXECUTION_HISTOGRAM
if (config->admissions_percentile > 99 || config->admissions_percentile < 50) {
fprintf(stderr, "admissions-percentile must be > 50 and <= 99 but was %u, defaulting to 70\n",
config->admissions_percentile);
config->admissions_percentile = 70;
}
#endif
#ifdef EXECUTION_REGRESSION
if (did_set[route_config_member_path_preprocess] == false) {
fprintf(stderr, "model path_preprocess field is required. Put zero if just default preprocessing\n");
return -1;
} else if (strcmp(config->path_preprocess, "0") == 0) {
config->path_preprocess = NULL;
}
if (did_set[route_config_member_model_bias] == false) {
fprintf(stderr, "model bias field is required\n");
return -1;
}
if (did_set[route_config_member_model_scale] == false) {
fprintf(stderr, "model scale field is required\n");
return -1;
}
if (config->model_scale == 0) {
fprintf(stderr, "model scale cannot be zero (to avoid divide by zero)\n");
return -1;
}
if (did_set[route_config_member_admissions_percentile] == false) {
fprintf(stderr, "admissions_percentile is required\n");
if (did_set[route_config_member_model_num_of_param] == false) {
fprintf(stderr, "model num_of_param field is required\n");
return -1;
}
if (did_set[route_config_member_model_beta1] == false) {
fprintf(stderr, "model beta1 field is required\n");
return -1;
}
if (config->model_beta1 == 0) {
fprintf(stderr, "model beta1 cannot be zero (to avoid divide by zero)\n");
return -1;
}
if (did_set[route_config_member_model_beta2] == false) {
fprintf(stderr, "model beta2 field is required. Put zero for just default preprocessing\n");
return -1;
}
if (config->model_num_of_param < 1) {
fprintf(stderr, "model num_of_param must be at least 1 (just default preprocessing)\n");
return -1;
} else if (config->model_num_of_param == 1) {
if (config->path_preprocess) {
fprintf(stderr, "model_num_of_param cannot be 1 when using tenant preprocessing\n");
return -1;
}
if (config->admissions_percentile > 99 || config->admissions_percentile < 50) {
fprintf(stderr, "admissions-percentile must be > 50 and <= 99 but was %u\n",
config->admissions_percentile);
config->model_beta2 = 1; /* This is to avoid divide-by-zero */
} else {
/* For now we just support up to two params */
assert(config->model_num_of_param == 2);
if (config->path_preprocess == NULL) {
fprintf(stderr, "model_num_of_param cannot be more than 1 when just default preprocessing\n");
return -1;
}
/* If the ratio is too big, admissions control is too coarse */
uint32_t ratio = config->relative_deadline_us / config->expected_execution_us;
if (ratio > ADMISSIONS_CONTROL_GRANULARITY) {
fprintf(stderr,
"Ratio of Deadline to Execution time cannot exceed admissions control "
"granularity of "
"%d\n",
ADMISSIONS_CONTROL_GRANULARITY);
if (config->model_beta2 == 0) {
fprintf(stderr, "model beta2 cannot be zero (to avoid divide by zero)\n");
return -1;
}
#endif
}
#endif
return 0;
}

@ -6,12 +6,10 @@
#include "json.h"
#include "route_config.h"
static const char *route_config_json_keys[route_config_member_len] = { "route",
"path",
"admissions-percentile",
"expected-execution-us",
"relative-deadline-us",
"http-resp-content-type" };
static const char *route_config_json_keys[route_config_member_len] =
{"route", "path", "admissions-percentile", "relative-deadline-us",
"path_preprocess", "model-bias", "model-scale", "model-num-of-param",
"model-beta1", "model-beta2", "http-resp-content-type"};
static inline int
route_config_set_key_once(bool *did_set, enum route_config_member member)
@ -30,8 +28,8 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
int tokens_size)
{
int i = tokens_base;
char key[32] = { 0 };
bool did_set[route_config_member_len] = { false };
char key[32] = {0};
bool did_set[route_config_member_len] = {false};
if (!has_valid_type(tokens[i], "Anonymous Route Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Route Config Object")) return -1;
@ -61,6 +59,11 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
if (route_config_set_key_once(did_set, route_config_member_path) == -1) return -1;
config->path = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_member_path_preprocess]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_path_preprocess) == -1) return -1;
config->path_preprocess = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_member_admissions_percentile]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_admissions_percentile) == -1)
@ -70,15 +73,6 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
route_config_json_keys[route_config_member_admissions_percentile],
&config->admissions_percentile);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_expected_execution_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_expected_execution_us) == -1)
return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_expected_execution_us],
&config->expected_execution_us);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_relative_deadline_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_relative_deadline_us) == -1)
@ -88,6 +82,49 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
route_config_json_keys[route_config_member_relative_deadline_us],
&config->relative_deadline_us);
if (rc < 0) return -1;
} else if (strcmp(key, "expected-execution-us") == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
printf("The \"expected-execution-us\" field has been deprecated, so no need.\n");
} else if (strcmp(key, route_config_json_keys[route_config_member_model_bias]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_bias) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_bias],
&config->model_bias);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_scale]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_scale) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_scale],
&config->model_scale);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_num_of_param]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_num_of_param) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_num_of_param],
&config->model_num_of_param);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_beta1]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_beta1) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_beta1],
&config->model_beta1);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_model_beta2]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_model_beta2) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_member_model_beta2],
&config->model_beta2);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_member_http_resp_content_type]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_http_resp_content_type) == -1)

@ -1,10 +1,10 @@
#pragma once
#include <pthread.h>
#include <sys/epoll.h> /* for epoll_create1(), epoll_ctl(), struct epoll_event */
#include <sys/types.h> /* for pid_t */
#include <stdatomic.h>
#include <stdbool.h>
#include <sys/epoll.h> /* for epoll_create1(), epoll_ctl(), struct epoll_event */
#include <sys/types.h> /* for pid_t */
#include "likely.h"
#include "types.h"

@ -1,12 +1,12 @@
#pragma once
#include <sys/mman.h>
#include <stddef.h>
#include <stdint.h>
#include <sys/mman.h>
#include "panic.h"
#include "tenant.h"
#include "sandbox_types.h"
#include "tenant.h"
/***************************
* Public API *

@ -15,7 +15,7 @@ sandbox_perf_log_print_header()
if (sandbox_perf_log == NULL) { perror("sandbox perf log"); }
fprintf(sandbox_perf_log, "id,tenant,route,state,deadline,actual,queued,uninitialized,allocated,initialized,"
"runnable,interrupted,preempted,"
"running_sys,running_user,asleep,returned,complete,error,proc_MHz,memory\n");
"running_sys,running_user,asleep,returned,complete,error,proc_MHz,payload_size\n");
}
/**
@ -36,8 +36,9 @@ sandbox_perf_log_print_entry(struct sandbox *sandbox)
* becomes more intelligent, then peak linear memory size needs to be tracked
* seperately from current linear memory size.
*/
fprintf(sandbox_perf_log, "%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u\n",
sandbox->id, sandbox->tenant->name, sandbox->route->route, sandbox_state_stringify(sandbox->state),
fprintf(sandbox_perf_log,
"%lu,%s,%s,%s,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%u,%u,%d,%d\n", sandbox->id,
sandbox->tenant->name, sandbox->route->route, sandbox_state_stringify(sandbox->state),
sandbox->route->relative_deadline, sandbox->total_time, queued_duration,
sandbox->duration_of_state[SANDBOX_UNINITIALIZED], sandbox->duration_of_state[SANDBOX_ALLOCATED],
sandbox->duration_of_state[SANDBOX_INITIALIZED], sandbox->duration_of_state[SANDBOX_RUNNABLE],
@ -45,7 +46,7 @@ sandbox_perf_log_print_entry(struct sandbox *sandbox)
sandbox->duration_of_state[SANDBOX_RUNNING_SYS], sandbox->duration_of_state[SANDBOX_RUNNING_USER],
sandbox->duration_of_state[SANDBOX_ASLEEP], sandbox->duration_of_state[SANDBOX_RETURNED],
sandbox->duration_of_state[SANDBOX_COMPLETE], sandbox->duration_of_state[SANDBOX_ERROR],
runtime_processor_speed_MHz);
runtime_processor_speed_MHz, sandbox->response_code, 0, sandbox->payload_size);
}
static inline void

@ -5,10 +5,10 @@
#include "arch/getcycles.h"
#include "local_runqueue.h"
#include "sandbox_types.h"
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_types.h"
/**
* Transitions a sandbox to the SANDBOX_ASLEEP state.

@ -3,7 +3,9 @@
#include <assert.h>
#include <stdint.h>
#include "admissions_control.h"
#include "arch/getcycles.h"
#include "execution_histogram.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
@ -46,15 +48,24 @@ sandbox_set_as_complete(struct sandbox *sandbox, sandbox_state_t last_state)
sandbox_state_totals_increment(SANDBOX_COMPLETE);
sandbox_state_totals_decrement(last_state);
struct route *route = sandbox->route;
#ifdef EXECUTION_HISTOGRAM
/* Execution Histogram Post Processing */
const uint64_t execution_duration = sandbox->duration_of_state[SANDBOX_RUNNING_USER]
+ sandbox->duration_of_state[SANDBOX_RUNNING_SYS];
execution_histogram_update(&route->execution_histogram, execution_duration);
#endif
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Post Processing */
admissions_info_update(&sandbox->route->admissions_info, sandbox->duration_of_state[SANDBOX_RUNNING_USER]
+ sandbox->duration_of_state[SANDBOX_RUNNING_SYS]);
admissions_control_subtract(sandbox->admissions_estimate);
#endif
/* Terminal State Logging for Sandbox */
sandbox_perf_log_print_entry(sandbox);
sandbox_summarize_page_allocations(sandbox);
route_latency_add(&sandbox->route->latency, sandbox->total_time);
route_latency_add(&route->latency, sandbox->total_time);
/* State Change Hooks */
sandbox_state_transition_from_hook(sandbox, last_state);

@ -3,16 +3,17 @@
#include <assert.h>
#include <stdint.h>
#include "admissions_control.h"
#include "arch/getcycles.h"
#include "listener_thread.h"
#include "local_runqueue.h"
#include "sandbox_state.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_summarize_page_allocations.h"
#include "panic.h"
/**
* Transitions a sandbox to the SANDBOX_ERROR state.
@ -48,14 +49,21 @@ sandbox_set_as_error(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_SYS) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_ERROR);
sandbox_state_totals_increment(SANDBOX_ERROR);
sandbox_state_totals_decrement(last_state);
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Post Processing */
admissions_control_subtract(sandbox->admissions_estimate);
#endif
/* Return HTTP session to listener core to be written back to client */
http_session_set_response_header(sandbox->http, 500);

@ -25,6 +25,10 @@ sandbox_set_as_interrupted(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
assert(last_state == SANDBOX_RUNNING_USER);
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
/* We do not append SANDBOX_INTERRUPTED to the sandbox_state_history because it would quickly fill the buffer */

@ -3,8 +3,8 @@
#include <assert.h>
#include <stdint.h>
#include "auto_buf.h"
#include "arch/getcycles.h"
#include "auto_buf.h"
#include "listener_thread.h"
#include "local_runqueue.h"
#include "panic.h"
@ -45,6 +45,9 @@ sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RETURNED);
@ -60,5 +63,7 @@ sandbox_set_as_returned(struct sandbox *sandbox, sandbox_state_t last_state)
sandbox_state_transition_from_hook(sandbox, last_state);
sandbox_state_transition_to_hook(sandbox, SANDBOX_RETURNED);
assert(sandbox->response_code == 0);
sandbox->response_code = 200;
sandbox_process_scheduler_updates(sandbox);
}

@ -41,6 +41,11 @@ sandbox_set_as_running_sys(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_USER) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RUNNING_SYS);
@ -55,6 +60,8 @@ sandbox_set_as_running_sys(struct sandbox *sandbox, sandbox_state_t last_state)
static inline void
sandbox_syscall(struct sandbox *sandbox)
{
if (sandbox->module->type == PREPROCESS_MODULE) return;
assert(sandbox->state == SANDBOX_RUNNING_USER);
sandbox_set_as_running_sys(sandbox, SANDBOX_RUNNING_USER);

@ -6,10 +6,10 @@
#include "arch/getcycles.h"
#include "current_sandbox.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_state_history.h"
#include "sandbox_state_transition.h"
#include "sandbox_types.h"
#include "sandbox_functions.h"
static inline void
sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
@ -37,6 +37,11 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
/* State Change Bookkeeping */
assert(now > sandbox->timestamp_of.last_state_change);
sandbox->last_state_duration = now - sandbox->timestamp_of.last_state_change;
if (last_state == SANDBOX_RUNNING_SYS) {
sandbox->remaining_exec = (sandbox->remaining_exec > sandbox->last_state_duration)
? sandbox->remaining_exec - sandbox->last_state_duration
: 0;
}
sandbox->duration_of_state[last_state] += sandbox->last_state_duration;
sandbox->timestamp_of.last_state_change = now;
sandbox_state_history_append(&sandbox->state_history, SANDBOX_RUNNING_USER);
@ -61,6 +66,8 @@ sandbox_set_as_running_user(struct sandbox *sandbox, sandbox_state_t last_state)
static inline void
sandbox_return(struct sandbox *sandbox)
{
if (sandbox->module->type == PREPROCESS_MODULE) return;
assert(sandbox->state == SANDBOX_RUNNING_SYS);
sandbox_set_as_running_user(sandbox, SANDBOX_RUNNING_SYS);
}

@ -9,11 +9,11 @@
#include "sandbox_state.h"
#include "sandbox_state_history.h"
#include "tenant.h"
#include "wasi.h"
#include "wasm_globals.h"
#include "wasm_memory.h"
#include "wasm_types.h"
#include "wasm_stack.h"
#include "wasm_globals.h"
#include "wasi.h"
#include "wasm_types.h"
/*********************
* Structs and Types *
@ -38,6 +38,7 @@ struct sandbox {
uint64_t id;
sandbox_state_t state;
struct sandbox_state_history state_history;
uint16_t response_code;
/* Accounting Info */
@ -61,10 +62,12 @@ struct sandbox {
uint64_t duration_of_state[SANDBOX_STATE_COUNT];
uint64_t last_state_duration;
uint64_t remaining_exec;
uint64_t absolute_deadline;
uint64_t admissions_estimate; /* estimated execution time (cycles) * runtime_admissions_granularity / relative
deadline (cycles) */
uint64_t total_time; /* Total time from Request to Response */
int payload_size;
/* System Interface State */
int32_t return_value;

@ -9,19 +9,19 @@
#include "global_request_scheduler_deque.h"
#include "global_request_scheduler_minheap.h"
#include "global_request_scheduler_mtds.h"
#include "local_cleanup_queue.h"
#include "local_runqueue.h"
#include "local_runqueue_minheap.h"
#include "local_runqueue_list.h"
#include "local_cleanup_queue.h"
#include "local_runqueue_minheap.h"
#include "local_runqueue_mtds.h"
#include "panic.h"
#include "sandbox_functions.h"
#include "sandbox_types.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_set_as_preempted.h"
#include "sandbox_set_as_runnable.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_types.h"
#include "scheduler_options.h"
@ -106,6 +106,31 @@ done:
return local_runqueue_get_next();
}
static inline struct sandbox *
scheduler_sjf_get_next()
{
struct sandbox *local = local_runqueue_get_next();
uint64_t local_rem_exec = local == NULL ? UINT64_MAX : local->remaining_exec;
struct sandbox *global = NULL;
uint64_t global_remaining_exec = global_request_scheduler_peek();
/* Try to pull and allocate from the global queue if earlier
* This will be placed at the head of the local runqueue */
if (global_remaining_exec < local_rem_exec) {
if (global_request_scheduler_remove_if_earlier(&global, local_rem_exec) == 0) {
assert(global != NULL);
assert(global->remaining_exec < local_rem_exec);
sandbox_prepare_execution_environment(global);
assert(global->state == SANDBOX_INITIALIZED);
sandbox_set_as_runnable(global, SANDBOX_INITIALIZED);
}
}
/* Return what is at the head of the local runqueue or NULL if empty */
return local_runqueue_get_next();
}
static inline struct sandbox *
scheduler_edf_get_next()
{
@ -163,6 +188,8 @@ scheduler_get_next()
return scheduler_mtdbf_get_next();
case SCHEDULER_MTDS:
return scheduler_mtds_get_next();
case SCHEDULER_SJF:
return scheduler_sjf_get_next();
case SCHEDULER_EDF:
return scheduler_edf_get_next();
case SCHEDULER_FIFO:
@ -177,12 +204,13 @@ scheduler_initialize()
{
switch (scheduler) {
case SCHEDULER_MTDBF:
// global_request_scheduler_mtdbf_initialize();
/* TODO: loading */
break;
case SCHEDULER_MTDS:
global_request_scheduler_mtds_initialize();
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
global_request_scheduler_minheap_initialize();
break;
case SCHEDULER_FIFO:
@ -204,6 +232,7 @@ scheduler_runqueue_initialize()
local_runqueue_mtds_initialize();
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
local_runqueue_minheap_initialize();
break;
case SCHEDULER_FIFO:
@ -222,6 +251,8 @@ scheduler_print(enum SCHEDULER variant)
return "FIFO";
case SCHEDULER_EDF:
return "EDF";
case SCHEDULER_SJF:
return "SJF";
case SCHEDULER_MTDS:
return "MTDS";
case SCHEDULER_MTDBF:
@ -287,6 +318,7 @@ scheduler_process_policy_specific_updates_on_interrupts(struct sandbox *interrup
case SCHEDULER_FIFO:
return;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
return;
case SCHEDULER_MTDS:
local_timeout_queue_process_promotions();

@ -2,10 +2,11 @@
enum SCHEDULER
{
SCHEDULER_FIFO = 0,
SCHEDULER_EDF = 1,
SCHEDULER_MTDS = 2,
SCHEDULER_MTDBF = 3
SCHEDULER_FIFO,
SCHEDULER_EDF,
SCHEDULER_SJF,
SCHEDULER_MTDS,
SCHEDULER_MTDBF
};
extern enum SCHEDULER scheduler;

@ -5,8 +5,8 @@
#include <stdint.h>
#include "debuglog.h"
#include "wasm_types.h"
#include "sledge_abi.h"
#include "wasm_types.h"
struct sledge_abi_symbols {
void *handle;

@ -1,7 +1,7 @@
#pragma once
#include <stdatomic.h>
#include <signal.h>
#include <stdatomic.h>
#include <stdlib.h>
#include "worker_thread.h"

@ -3,10 +3,10 @@
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "debuglog.h"

@ -1,7 +1,7 @@
#pragma once
#include <assert.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <string.h>
@ -9,8 +9,8 @@
#include <unistd.h>
#include "debuglog.h"
#include "panic.h"
#include "likely.h"
#include "panic.h"
static inline void
tcp_session_close(int client_socket, struct sockaddr *client_address)
@ -21,7 +21,7 @@ tcp_session_close(int client_socket, struct sockaddr *client_address)
assert(client_socket != STDERR_FILENO);
if (unlikely(close(client_socket) < 0)) {
char client_address_text[INET6_ADDRSTRLEN] = { '\0' };
char client_address_text[INET6_ADDRSTRLEN] = {'\0'};
if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) {
debuglog("Failed to log client_address: %s", strerror(errno));
}

@ -45,8 +45,10 @@ tenant_config_print(struct tenant_config *config)
{
printf("[Tenant] Name: %s\n", config->name);
printf("[Tenant] Path: %d\n", config->port);
printf("[Tenant] Replenishment Period (us): %u\n", config->replenishment_period_us);
printf("[Tenant] Max Budget (us): %u\n", config->max_budget_us);
if (scheduler == SCHEDULER_MTDS) {
printf("[Tenant] Replenishment Period (us): %u\n", config->replenishment_period_us);
printf("[Tenant] Max Budget (us): %u\n", config->max_budget_us);
}
printf("[Tenant] Routes Size: %zu\n", config->routes_len);
for (int i = 0; i < config->routes_len; i++) { route_config_print(&config->routes[i]); }
}
@ -71,19 +73,19 @@ tenant_config_validate(struct tenant_config *config, bool *did_set)
if (scheduler == SCHEDULER_MTDS) {
if (did_set[tenant_config_member_replenishment_period_us] == false) {
fprintf(stderr, "replenishment-period-us field is required\n");
return -1;
fprintf(stderr, "replenishment-period-us field is missing, so defaulting to 0\n");
config->replenishment_period_us = 0;
}
if (config->replenishment_period_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX) {
fprintf(stderr, "Relative-deadline-us must be between 0 and %u, was %u\n",
fprintf(stderr, "relative-deadline-us must be between 0 and %u, was %u\n",
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, config->replenishment_period_us);
return -1;
}
if (did_set[tenant_config_member_max_budget_us] == false) {
fprintf(stderr, "max-budget-us field is required\n");
return -1;
fprintf(stderr, "max-budget-us field is missing, so defaulting to 0\n");
config->max_budget_us = 0;
}
if (config->max_budget_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX) {

@ -9,8 +9,8 @@
#include "route_config_parse.h"
#include "tenant_config.h"
static const char *tenant_config_json_keys[tenant_config_member_len] = { "name", "port", "replenishment-period-us",
"max-budget-us", "routes" };
static const char *tenant_config_json_keys[tenant_config_member_len] = {"name", "port", "replenishment-period-us",
"max-budget-us", "routes"};
static inline int
tenant_config_set_key_once(bool *did_set, enum tenant_config_member member)
@ -29,8 +29,8 @@ tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_
int tokens_size)
{
int i = tokens_base;
char key[32] = { 0 };
bool did_set[tenant_config_member_len] = { false };
char key[32] = {0};
bool did_set[tenant_config_member_len] = {false};
if (!has_valid_type(tokens[i], "Anonymous Tenant Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Tenant Config Object")) return -1;

@ -3,16 +3,15 @@
#include <stdint.h>
#include <string.h>
#include "admissions_info.h"
#include "http.h"
#include "listener_thread.h"
#include "module_database.h"
#include "panic.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
#include "scheduler_options.h"
#include "tenant.h"
#include "tenant_config.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
int tenant_database_add(struct tenant *tenant);
struct tenant *tenant_database_find_by_name(char *name);
@ -30,6 +29,7 @@ tenant_policy_specific_init(struct tenant *tenant, struct tenant_config *config)
case SCHEDULER_FIFO:
break;
case SCHEDULER_EDF:
case SCHEDULER_SJF:
break;
case SCHEDULER_MTDS:
/* Deferable Server Initialization */
@ -103,7 +103,7 @@ tenant_alloc(struct tenant_config *config)
struct module *module = module_database_find_by_path(&tenant->module_db, config->routes[i].path);
if (module == NULL) {
/* Ownership of path moves here */
module = module_alloc(config->routes[i].path);
module = module_alloc(config->routes[i].path, APP_MODULE);
if (module != NULL) {
module_database_add(&tenant->module_db, module);
config->routes[i].path = NULL;
@ -115,8 +115,30 @@ tenant_alloc(struct tenant_config *config)
assert(module != NULL);
struct module *module_proprocess = NULL;
#ifdef EXECUTION_REGRESSION
if (config->routes[i].path_preprocess) {
module_proprocess = module_database_find_by_path(&tenant->module_db,
config->routes[i].path_preprocess);
if (module_proprocess == NULL) {
/* Ownership of path moves here */
module_proprocess = module_alloc(config->routes[i].path_preprocess, PREPROCESS_MODULE);
if (module_proprocess != NULL) {
module_database_add(&tenant->module_db, module_proprocess);
config->routes[i].path_preprocess = NULL;
}
} else {
free(config->routes[i].path_preprocess);
config->routes[i].path_preprocess = NULL;
}
assert(module_proprocess != NULL);
}
#endif
/* Ownership of config's route and http_resp_content_type move here */
int rc = http_router_add_route(&tenant->router, &config->routes[i], module);
int rc = http_router_add_route(&tenant->router, &config->routes[i], module, module_proprocess);
if (unlikely(rc != 0)) {
panic("Tenant %s defined %lu routes, but router failed to grow beyond %lu\n", tenant->name,
config->routes_len, tenant->router.capacity);
@ -160,5 +182,6 @@ get_next_timeout_of_tenant(uint64_t replenishment_period)
* @param tenant
* @returns 0 on success, -1 on error
*/
int tenant_listen(struct tenant *tenant);
int listener_thread_register_tenant(struct tenant *tenant);
int tenant_listen(struct tenant *tenant);
int listener_thread_register_tenant(struct tenant *tenant);
void tenant_preprocess(struct http_session *session);

@ -85,9 +85,9 @@ wasm_globals_set_i32(struct vec_wasm_global_t *globals, uint32_t idx, int32_t va
wasm_global_t *current = vec_wasm_global_t_get(globals, idx);
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I32, .value = value });
int rc =
vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I32, .value = value});
return rc;
}
@ -99,8 +99,8 @@ wasm_globals_set_i64(struct vec_wasm_global_t *globals, uint32_t idx, int64_t va
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
// Returns -1 if idx > capacity
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I64, .value = value });
int rc =
vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I64, .value = value});
return rc;
}

@ -8,8 +8,8 @@
#include <sys/mman.h>
#include "ps_list.h"
#include "types.h" /* PAGE_SIZE */
#include "sledge_abi.h"
#include "types.h" /* PAGE_SIZE */
#include "wasm_types.h"
#define WASM_MEMORY_MAX (uint64_t) UINT32_MAX + 1

@ -1,7 +1,7 @@
#pragma once
#include "sledge_abi.h"
#include "wasm_memory.h"
#include "wasm_table.h"
#include "sledge_abi.h"
/* This structure is the runtime representation of the unique state of a module instance
* Currently this is not spec-compliant, as it only supports a single table and a single memory and it excludes many

@ -2,9 +2,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <strings.h>
#include <sys/mman.h>
#include "ps_list.h"
#include "types.h"

@ -109,5 +109,5 @@ wasm_table_set(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t
/* TODO: atomic for multiple concurrent invocations? Issue #97 */
if (wasm_table->buffer[idx].type_id == type_id && wasm_table->buffer[idx].func_pointer == pointer) return;
wasm_table->buffer[idx] = (struct sledge_abi__wasm_table_entry){ .type_id = type_id, .func_pointer = pointer };
wasm_table->buffer[idx] = (struct sledge_abi__wasm_table_entry){.type_id = type_id, .func_pointer = pointer};
}

@ -8,6 +8,8 @@
#include "panic.h"
#include "runtime.h"
#ifdef ADMISSIONS_CONTROL
/*
* Unitless estimate of the instantaneous fraction of system capacity required to complete all previously
* admitted work. This is used to calculate free capacity as part of admissions control
@ -19,40 +21,32 @@
* success or failure)
*/
#ifdef ADMISSIONS_CONTROL
_Atomic uint64_t admissions_control_admitted;
uint64_t admissions_control_capacity;
const double admissions_control_overhead = 0.2;
#endif
void
admissions_control_initialize()
{
#ifdef ADMISSIONS_CONTROL
atomic_init(&admissions_control_admitted, 0);
admissions_control_capacity = runtime_worker_threads_count * ADMISSIONS_CONTROL_GRANULARITY
* ((double)1.0 - admissions_control_overhead);
#endif
}
void
admissions_control_add(uint64_t admissions_estimate)
{
#ifdef ADMISSIONS_CONTROL
assert(admissions_estimate > 0);
atomic_fetch_add(&admissions_control_admitted, admissions_estimate);
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity);
#endif
#endif /* ADMISSIONS_CONTROL */
}
void
admissions_control_subtract(uint64_t admissions_estimate)
{
#ifdef ADMISSIONS_CONTROL
/* Assumption: Should never underflow */
if (unlikely(admissions_estimate > admissions_control_admitted)) panic("Admissions Estimate underflow\n");
@ -61,14 +55,11 @@ admissions_control_subtract(uint64_t admissions_estimate)
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Runtime Admitted: %lu / %lu\n", admissions_control_admitted, admissions_control_capacity);
#endif
#endif /* ADMISSIONS_CONTROL */
}
uint64_t
admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t relative_deadline)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline != 0);
uint64_t admissions_estimate = (estimated_execution * (uint64_t)ADMISSIONS_CONTROL_GRANULARITY)
/ relative_deadline;
@ -76,31 +67,15 @@ admissions_control_calculate_estimate(uint64_t estimated_execution, uint64_t rel
panic("Ratio of Deadline to Execution time cannot exceed %d\n", ADMISSIONS_CONTROL_GRANULARITY);
return admissions_estimate;
#else
return 0;
#endif
}
uint64_t
admissions_control_calculate_estimate_us(uint32_t estimated_execution_us, uint32_t relative_deadline_us)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline_us != 0);
return (uint64_t)((uint64_t)(estimated_execution_us * ADMISSIONS_CONTROL_GRANULARITY)) / relative_deadline_us;
#else
return 0;
#endif
}
void
admissions_control_log_decision(uint64_t admissions_estimate, bool admitted)
{
#ifdef ADMISSIONS_CONTROL
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Admitted: %lu, Capacity: %lu, Estimate: %lu, Admitted? %s\n", admissions_control_admitted,
admissions_control_capacity, admissions_estimate, admitted ? "yes" : "no");
#endif /* LOG_ADMISSIONS_CONTROL */
#endif /* ADMISSIONS_CONTROL */
}
uint64_t
@ -108,7 +83,6 @@ admissions_control_decide(uint64_t admissions_estimate)
{
uint64_t work_admitted = 1; /* Nominal non-zero value in case admissions control is disabled */
#ifdef ADMISSIONS_CONTROL
if (unlikely(admissions_estimate == 0)) panic("Admissions estimate should never be zero");
uint64_t total_admitted = atomic_load(&admissions_control_admitted);
@ -121,7 +95,8 @@ admissions_control_decide(uint64_t admissions_estimate)
admissions_control_add(admissions_estimate);
work_admitted = admissions_estimate;
}
#endif /* ADMISSIONS_CONTROL */
return work_admitted;
}
#endif /* ADMISSIONS_CONTROL */

@ -1,56 +0,0 @@
#include "admissions_control.h"
#include "admissions_info.h"
#include "debuglog.h"
#include "perf_window.h"
/**
* Initializes perf window
* @param admissions_info
*/
void
admissions_info_initialize(struct admissions_info *admissions_info, uint8_t percentile, uint64_t expected_execution,
uint64_t relative_deadline)
{
#ifdef ADMISSIONS_CONTROL
assert(relative_deadline > 0);
assert(expected_execution > 0);
admissions_info->relative_deadline = relative_deadline;
admissions_info->estimate = admissions_control_calculate_estimate(expected_execution, relative_deadline);
debuglog("Initial Estimate: %lu\n", admissions_info->estimate);
assert(admissions_info != NULL);
perf_window_initialize(&admissions_info->perf_window);
if (unlikely(percentile < 50 || percentile > 99)) panic("Invalid admissions percentile");
admissions_info->percentile = percentile;
admissions_info->control_index = PERF_WINDOW_CAPACITY * percentile / 100;
#ifdef LOG_ADMISSIONS_CONTROL
debuglog("Percentile: %u\n", admissions_info->percentile);
debuglog("Control Index: %d\n", admissions_info->control_index);
#endif
#endif
}
/*
* Adds an execution value to the perf window and calculates and caches and updated estimate
* @param admissions_info
* @param execution_duration
*/
void
admissions_info_update(struct admissions_info *admissions_info, uint64_t execution_duration)
{
#ifdef ADMISSIONS_CONTROL
struct perf_window *perf_window = &admissions_info->perf_window;
lock_node_t node = {};
lock_lock(&perf_window->lock, &node);
perf_window_add(perf_window, execution_duration);
uint64_t estimated_execution = perf_window_get_percentile(perf_window, admissions_info->percentile,
admissions_info->control_index);
admissions_info->estimate = admissions_control_calculate_estimate(estimated_execution,
admissions_info->relative_deadline);
lock_unlock(&perf_window->lock, &node);
#endif
}

@ -1,15 +1,14 @@
#include <threads.h>
#include <setjmp.h>
#include <threads.h>
#include "current_sandbox.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_asleep.h"
#include "sandbox_set_as_complete.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_returned.h"
#include "sandbox_set_as_complete.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_running_user.h"
#include "scheduler.h"
#include "software_interrupt.h"
#include "wasi.h"
@ -194,5 +193,5 @@ current_sandbox_start(void)
current_sandbox_wasm_trap_handler(rc);
}
current_sandbox_fini();
if (sandbox->module->type == APP_MODULE) current_sandbox_fini();
}

@ -1,20 +1,20 @@
#include <stdlib.h>
#include "current_sandbox.h"
#include "wasm_module_instance.h"
#include "wasm_memory.h"
#include "wasm_module_instance.h"
thread_local struct wasm_module_instance sledge_abi__current_wasm_module_instance = {
.abi.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.max = 0,
.capacity = 0,
.buffer = NULL,
},
.abi.table = NULL,
.abi.wasmg_0 = 0xDEADBEEF,
.wasi_context = NULL,
.abi.memory =
(struct sledge_abi__wasm_memory){
.size = 0,
.max = 0,
.capacity = 0,
.buffer = NULL,
},
.abi.table = NULL,
.abi.wasmg_0 = 0xDEADBEEF,
.wasi_context = NULL,
};
void

@ -0,0 +1,50 @@
#ifdef EXECUTION_HISTOGRAM
#include "execution_histogram.h"
#include "debuglog.h"
#include "perf_window.h"
/**
* Initializes execution_histogram and its perf window
* @param execution_histogram
*/
void
execution_histogram_initialize(struct execution_histogram *execution_histogram, uint8_t percentile,
uint64_t expected_execution)
{
assert(expected_execution > 0);
execution_histogram->estimated_execution = expected_execution;
assert(execution_histogram != NULL);
perf_window_initialize(&execution_histogram->perf_window);
if (unlikely(percentile < 50 || percentile > 99)) panic("Invalid percentile");
execution_histogram->percentile = percentile;
execution_histogram->control_index = PERF_WINDOW_CAPACITY * percentile / 100;
#ifdef LOG_EXECUTION_HISTOGRAM
debuglog("Percentile: %u\n", execution_histogram->percentile);
debuglog("Control Index: %d\n", execution_histogram->control_index);
#endif
}
/*
* Adds an execution value to the perf window
* @param execution_histogram
* @param execution_duration
*/
void
execution_histogram_update(struct execution_histogram *execution_histogram, uint64_t execution_duration)
{
struct perf_window *perf_window = &execution_histogram->perf_window;
lock_node_t node = {};
lock_lock(&perf_window->lock, &node);
perf_window_add(perf_window, execution_duration);
uint64_t estimated_execution = perf_window_get_percentile(perf_window, execution_histogram->percentile,
execution_histogram->control_index);
execution_histogram->estimated_execution = estimated_execution;
lock_unlock(&perf_window->lock, &node);
}
#endif

@ -24,9 +24,9 @@ uninitialized_peek()
/* The global of our polymorphic interface */
static struct global_request_scheduler_config global_request_scheduler = { .add_fn = uninitialized_add,
.remove_fn = uninitialized_remove,
.peek_fn = uninitialized_peek };
static struct global_request_scheduler_config global_request_scheduler = {.add_fn = uninitialized_add,
.remove_fn = uninitialized_remove,
.peek_fn = uninitialized_peek};
/**
* Initializes the polymorphic interface with a concrete implementation

@ -1,8 +1,8 @@
#include "global_request_scheduler.h"
#include "global_request_scheduler_deque.h"
#include "global_request_scheduler.h"
#include "runtime.h"
#define GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY (1 << 19)
#define GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY (1 << 12)
static struct deque_sandbox *global_request_scheduler_deque;
@ -57,11 +57,10 @@ global_request_scheduler_deque_initialize()
deque_init_sandbox(global_request_scheduler_deque, GLOBAL_REQUEST_SCHEDULER_DEQUE_CAPACITY);
/* Register Function Pointers for Abstract Scheduling API */
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_deque_add,
.remove_fn = global_request_scheduler_deque_remove,
.remove_if_earlier_fn = global_request_scheduler_deque_remove_if_earlier
};
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_deque_add,
.remove_fn = global_request_scheduler_deque_remove,
.remove_if_earlier_fn =
global_request_scheduler_deque_remove_if_earlier};
global_request_scheduler_initialize(&config);
}

@ -43,10 +43,10 @@ global_request_scheduler_minheap_remove(struct sandbox **removed_sandbox)
* @returns 0 if successful, -ENOENT if empty or if request isn't earlier than target_deadline
*/
int
global_request_scheduler_minheap_remove_if_earlier(struct sandbox **removed_sandbox, uint64_t target_deadline)
global_request_scheduler_minheap_remove_if_earlier(struct sandbox **removed_sandbox, uint64_t target_latest_start)
{
return priority_queue_dequeue_if_earlier(global_request_scheduler_minheap, (void **)removed_sandbox,
target_deadline);
target_latest_start);
}
/**
@ -65,6 +65,8 @@ uint64_t
sandbox_get_priority_fn(void *element)
{
struct sandbox *sandbox = (struct sandbox *)element;
if (scheduler == SCHEDULER_SJF) return sandbox->remaining_exec;
assert(scheduler == SCHEDULER_EDF);
return sandbox->absolute_deadline;
};
@ -77,12 +79,11 @@ global_request_scheduler_minheap_initialize()
{
global_request_scheduler_minheap = priority_queue_initialize(4096, true, sandbox_get_priority_fn);
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_minheap_add,
.remove_fn = global_request_scheduler_minheap_remove,
.remove_if_earlier_fn = global_request_scheduler_minheap_remove_if_earlier,
.peek_fn = global_request_scheduler_minheap_peek
};
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_minheap_add,
.remove_fn = global_request_scheduler_minheap_remove,
.remove_if_earlier_fn =
global_request_scheduler_minheap_remove_if_earlier,
.peek_fn = global_request_scheduler_minheap_peek};
global_request_scheduler_initialize(&config);
}

@ -230,12 +230,11 @@ global_request_scheduler_mtds_initialize()
lock_init(&global_lock);
struct global_request_scheduler_config config = {
.add_fn = global_request_scheduler_mtds_add,
.remove_fn = global_request_scheduler_mtds_remove,
.remove_if_earlier_fn = global_request_scheduler_mtds_remove_if_earlier,
.peek_fn = global_request_scheduler_mtds_peek
};
struct global_request_scheduler_config config = {.add_fn = global_request_scheduler_mtds_add,
.remove_fn = global_request_scheduler_mtds_remove,
.remove_if_earlier_fn =
global_request_scheduler_mtds_remove_if_earlier,
.peek_fn = global_request_scheduler_mtds_peek};
global_request_scheduler_initialize(&config);
}

@ -3,8 +3,8 @@
#include "debuglog.h"
#include "http.h"
#include "http_request.h"
#include "http_parser_settings.h"
#include "http_request.h"
#include "likely.h"
http_parser_settings runtime_http_parser_settings;
@ -211,7 +211,7 @@ http_parser_settings_on_header_end(http_parser *parser)
}
}
const char *http_methods[] = { "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" };
const char *http_methods[] = {"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"};
/**
* http-parser callback called for HTTP Bodies

@ -18,8 +18,8 @@ http_session_perf_log_print_entry(struct http_session *http_session)
const uint64_t sent_duration = http_session->response_sent_timestamp - http_session->response_takeoff_timestamp;
const uint64_t total_lifetime = http_session->response_sent_timestamp - http_session->request_arrival_timestamp;
fprintf(http_session_perf_log, "%s,%s,%u,%lu,%lu,%lu,%lu,%lu,%u\n", http_session->tenant->name,
fprintf(http_session_perf_log, "%s,%s,%u,%lu,%lu,%lu,%lu,%lu,%lu,%u\n", http_session->tenant->name,
http_session->http_request.full_url, http_session->state, http_session->response_header_written,
http_session->response_body_written, receive_duration, sent_duration, total_lifetime,
runtime_processor_speed_MHz);
http_session->preprocessing_duration, runtime_processor_speed_MHz);
}

@ -2,16 +2,18 @@
#include <unistd.h>
#include "arch/getcycles.h"
#include "execution_regression.h"
#include "global_request_scheduler.h"
#include "http_session_perf_log.h"
#include "listener_thread.h"
#include "metrics_server.h"
#include "module.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "sandbox_perf_log.h"
#include "tcp_session.h"
#include "tenant.h"
#include "tenant_functions.h"
#include "http_session_perf_log.h"
static void listener_thread_unregister_http_session(struct http_session *http);
static void panic_on_epoll_error(struct epoll_event *evt);
@ -193,11 +195,34 @@ on_client_request_receiving(struct http_session *session)
{
/* Read HTTP request */
int rc = http_session_receive_request(session, (void_star_cb)listener_thread_register_http_session);
if (likely(rc == 0)) {
/* Check if the route is accurate only when the URL is downloaded. Stop downloading if inaccurate. */
if (session->route == NULL && strlen(session->http_request.full_url) > 0) {
struct route *route = http_router_match_route(&session->tenant->router, session->http_request.full_url);
if (route == NULL) {
debuglog("Did not match any routes\n");
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 404);
on_client_response_header_sending(session);
return;
}
session->route = route;
}
if (rc == 0) {
#ifdef EXECUTION_REGRESSION
if (!session->did_preprocessing) tenant_preprocess(session);
#endif
on_client_request_received(session);
return;
} else if (unlikely(rc == -EAGAIN)) {
/* session blocked and registered to epoll so continue to next handle */
} else if (rc == -EAGAIN) {
/* session blocked and registered to epoll, so continue to next handle */
#ifdef EXECUTION_REGRESSION
/* try tenant preprocessing if min 4k Bytes received */
if (!session->did_preprocessing && session->http_request.body_length_read > 4096)
tenant_preprocess(session);
#endif
return;
} else if (rc < 0) {
debuglog("Failed to receive or parse request\n");
@ -215,30 +240,29 @@ on_client_request_received(struct http_session *session)
{
assert(session->state == HTTP_SESSION_RECEIVED_REQUEST);
session->request_downloaded_timestamp = __getcycles();
struct route *route = session->route;
uint64_t estimated_execution = route->execution_histogram.estimated_execution;
uint64_t work_admitted = 1;
struct route *route = http_router_match_route(&session->tenant->router, session->http_request.full_url);
if (route == NULL) {
debuglog("Did not match any routes\n");
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 404);
on_client_response_header_sending(session);
return;
}
session->route = route;
#ifdef EXECUTION_REGRESSION
estimated_execution = get_regression_prediction(session);
#endif
#ifdef ADMISSIONS_CONTROL
/*
* Perform admissions control.
* If 0, workload was rejected, so close with 429 "Too Many Requests" and continue
* TODO: Consider providing a Retry-After header
*/
uint64_t work_admitted = admissions_control_decide(route->admissions_info.estimate);
uint64_t admissions_estimate = admissions_control_calculate_estimate(estimated_execution,
route->relative_deadline);
work_admitted = admissions_control_decide(admissions_estimate);
if (work_admitted == 0) {
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 429);
on_client_response_header_sending(session);
return;
}
#endif
/* Allocate a Sandbox */
session->state = HTTP_SESSION_EXECUTING;
@ -251,9 +275,15 @@ on_client_request_received(struct http_session *session)
return;
}
sandbox->remaining_exec = estimated_execution;
/* If the global request scheduler is full, return a 429 to the client */
if (unlikely(global_request_scheduler_add(sandbox) == NULL)) {
debuglog("Failed to add sandbox to global queue\n");
// debuglog("Failed to add sandbox to global queue\n");
sandbox->response_code = 4290;
sandbox->state = SANDBOX_ERROR;
sandbox_perf_log_print_entry(sandbox);
sandbox->http = NULL;
sandbox_free(sandbox);
session->state = HTTP_SESSION_EXECUTION_COMPLETE;
http_session_set_response_header(session, 429);

@ -2,8 +2,8 @@
#include "current_sandbox.h"
#include "global_request_scheduler.h"
#include "local_runqueue_list.h"
#include "local_runqueue.h"
#include "local_runqueue_list.h"
#include "sandbox_functions.h"
thread_local static struct ps_list_head local_runqueue_list;
@ -81,9 +81,9 @@ local_runqueue_list_initialize()
ps_list_head_init(&local_runqueue_list);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = { .add_fn = local_runqueue_list_append,
.is_empty_fn = local_runqueue_list_is_empty,
.delete_fn = local_runqueue_list_remove,
.get_next_fn = local_runqueue_list_get_next };
struct local_runqueue_config config = {.add_fn = local_runqueue_list_append,
.is_empty_fn = local_runqueue_list_is_empty,
.delete_fn = local_runqueue_list_remove,
.get_next_fn = local_runqueue_list_get_next};
local_runqueue_initialize(&config);
};

@ -9,8 +9,8 @@
#include "local_runqueue_minheap.h"
#include "panic.h"
#include "priority_queue.h"
#include "sandbox_functions.h"
#include "runtime.h"
#include "sandbox_functions.h"
thread_local static struct priority_queue *local_runqueue_minheap;
@ -84,10 +84,10 @@ local_runqueue_minheap_initialize()
local_runqueue_minheap = priority_queue_initialize(RUNTIME_RUNQUEUE_SIZE, false, sandbox_get_priority);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = { .add_fn = local_runqueue_minheap_add,
.is_empty_fn = local_runqueue_minheap_is_empty,
.delete_fn = local_runqueue_minheap_delete,
.get_next_fn = local_runqueue_minheap_get_next };
struct local_runqueue_config config = {.add_fn = local_runqueue_minheap_add,
.is_empty_fn = local_runqueue_minheap_is_empty,
.delete_fn = local_runqueue_minheap_delete,
.get_next_fn = local_runqueue_minheap_get_next};
local_runqueue_initialize(&config);
}

@ -9,9 +9,9 @@
#include "local_runqueue_mtds.h"
#include "panic.h"
#include "priority_queue.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "tenant_functions.h"
#include "runtime.h"
thread_local static struct priority_queue *local_runqueue_mtds_guaranteed;
thread_local static struct priority_queue *local_runqueue_mtds_default;
@ -172,10 +172,10 @@ local_runqueue_mtds_initialize()
perworker_tenant_get_priority);
/* Register Function Pointers for Abstract Scheduling API */
struct local_runqueue_config config = { .add_fn = local_runqueue_mtds_add,
.is_empty_fn = local_runqueue_mtds_is_empty,
.delete_fn = local_runqueue_mtds_delete,
.get_next_fn = local_runqueue_mtds_get_next };
struct local_runqueue_config config = {.add_fn = local_runqueue_mtds_add,
.is_empty_fn = local_runqueue_mtds_is_empty,
.delete_fn = local_runqueue_mtds_delete,
.get_next_fn = local_runqueue_mtds_get_next};
local_runqueue_initialize(&config);
}

@ -2,25 +2,25 @@
#include <dlfcn.h>
#include <math.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef LOG_TO_FILE
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
#include "json_parse.h"
#include "pretty_print.h"
#include "debuglog.h"
#include "json_parse.h"
#include "listener_thread.h"
#include "panic.h"
#include "pretty_print.h"
#include "runtime.h"
#include "sandbox_perf_log.h"
#include "sandbox_types.h"
@ -40,7 +40,7 @@ enum RUNTIME_SIGALRM_HANDLER runtime_sigalrm_handler = RUNTIME_SIGALRM_HANDLER_B
bool runtime_preemption_enabled = true;
bool runtime_worker_spinloop_pause_enabled = false;
uint32_t runtime_quantum_us = 5000; /* 5ms */
uint32_t runtime_quantum_us = 1000; /* 1ms */
uint64_t runtime_boot_timestamp;
pid_t runtime_pid = 0;
@ -105,7 +105,7 @@ runtime_allocate_available_cores()
static inline void
runtime_get_processor_speed_MHz(void)
{
char *proc_mhz_raw = getenv("PROC_MHZ");
char *proc_mhz_raw = getenv("SLEDGE_PROC_MHZ");
FILE *cmd = NULL;
if (proc_mhz_raw != NULL) {
@ -116,7 +116,7 @@ runtime_get_processor_speed_MHz(void)
usleep(200000); /* wait a bit for the workers to launch for more accuracy */
/* Get the average of the cpufreqs only for worker cores (no event core and reserved) */
char command[128] = { 0 };
char command[128] = {0};
sprintf(command, "grep '^cpu MHz' /proc/cpuinfo | sed -n '%u,%up' | \
awk '{ total += $4; count++ } END { print total/count }'",
runtime_first_worker_processor + 1,
@ -127,6 +127,7 @@ runtime_get_processor_speed_MHz(void)
char buff[16];
size_t n = fread(buff, 1, sizeof(buff) - 1, cmd);
buff[n] = '\0';
pclose(cmd);
float processor_speed_MHz;
n = sscanf(buff, "%f", &processor_speed_MHz);
@ -139,7 +140,6 @@ runtime_get_processor_speed_MHz(void)
pretty_print_key_value("Worker CPU Freq", "%u MHz\n", runtime_processor_speed_MHz);
done:
pclose(cmd);
return;
err:
goto done;
@ -208,10 +208,12 @@ runtime_configure()
scheduler = SCHEDULER_MTDS;
} else if (strcmp(scheduler_policy, "EDF") == 0) {
scheduler = SCHEDULER_EDF;
} else if (strcmp(scheduler_policy, "SJF") == 0) {
scheduler = SCHEDULER_SJF;
} else if (strcmp(scheduler_policy, "FIFO") == 0) {
scheduler = SCHEDULER_FIFO;
} else {
panic("Invalid scheduler policy: %s. Must be {MTDBF|MTDS|EDF|FIFO}\n", scheduler_policy);
panic("Invalid scheduler policy: %s. Must be {MTDBF|MTDS|EDF|SJF|FIFO}\n", scheduler_policy);
}
pretty_print_key_value("Scheduler Policy", "%s\n", scheduler_print(scheduler));
@ -284,6 +286,18 @@ log_compiletime_config()
pretty_print_key_disabled("Admissions Control");
#endif
#ifdef EXECUTION_HISTOGRAM
pretty_print_key_enabled("Execution Histogram");
#else
pretty_print_key_disabled("Execution Histogram");
#endif
#ifdef EXECUTION_REGRESSION
pretty_print_key_enabled("Execution Regression");
#else
pretty_print_key_disabled("Execution Regression");
#endif
/* Debugging Flags */
printf("Static Compiler Flags (Debugging):\n");

@ -11,8 +11,8 @@
#include "metrics_server.h"
#include "proc_stat.h"
#include "runtime.h"
#include "sandbox_total.h"
#include "sandbox_state.h"
#include "sandbox_total.h"
#include "tcp_server.h"
/* We run threads on the "reserved OS core" using blocking semantics */

@ -44,7 +44,8 @@ module_init(struct module *module, char *path)
rc = sledge_abi_symbols_init(&module->abi, path);
if (rc != 0) goto err;
module->pools = calloc(runtime_worker_threads_count, sizeof(struct module_pool));
module->pools = calloc((module->type == APP_MODULE ? runtime_worker_threads_count : 1),
sizeof(struct module_pool));
module->path = path;
@ -106,7 +107,7 @@ module_free(struct module *module)
*/
struct module *
module_alloc(char *path)
module_alloc(char *path, enum module_type type)
{
size_t alignment = (size_t)CACHE_PAD;
size_t size_to_alloc = (size_t)round_to_cache_pad(sizeof(struct module));
@ -120,6 +121,7 @@ module_alloc(char *path)
};
memset(module, 0, size_to_alloc);
module->type = type;
int rc = module_init(module, path);
if (rc < 0) goto init_err;

@ -1,14 +1,13 @@
#include <arpa/inet.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <pthread.h>
#include "admissions_control.h"
#include "arch/context.h"
@ -19,10 +18,10 @@
#include "listener_thread.h"
#include "module.h"
#include "runtime.h"
#include "sandbox_perf_log.h"
#include "sandbox_total.h"
#include "scheduler.h"
#include "software_interrupt.h"
#include "sandbox_perf_log.h"
/***************************
* Shared Process State *
@ -63,8 +62,8 @@ runtime_set_resource_limits_to_max()
char lim[uint64_t_max_digits + 1];
char max[uint64_t_max_digits + 1];
uint64_t resources[] = { RLIMIT_DATA, RLIMIT_NOFILE };
char *resource_names[] = { "RLIMIT_DATA", "RLIMIT_NOFILE" };
uint64_t resources[] = {RLIMIT_DATA, RLIMIT_NOFILE};
char *resource_names[] = {"RLIMIT_DATA", "RLIMIT_NOFILE"};
for (int i = 0; i < sizeof(resources) / sizeof(resources[0]); i++) {
int resource = resources[i];
@ -118,7 +117,11 @@ runtime_initialize(void)
signal(SIGQUIT, runtime_cleanup);
http_parser_settings_initialize();
#ifdef ADMISSIONS_CONTROL
/* Admissions Control Setup */
admissions_control_initialize();
#endif
}
static void

@ -8,9 +8,9 @@
#include "pool.h"
#include "runtime.h"
#include "sandbox_functions.h"
#include "sandbox_set_as_allocated.h"
#include "sandbox_set_as_error.h"
#include "sandbox_set_as_initialized.h"
#include "sandbox_set_as_allocated.h"
#include "sandbox_total.h"
#include "wasm_memory.h"
#include "wasm_stack.h"
@ -154,6 +154,7 @@ sandbox_init(struct sandbox *sandbox, struct module *module, struct http_session
sandbox->route = route;
sandbox->absolute_deadline = sandbox->timestamp_of.allocation + sandbox->route->relative_deadline;
sandbox->payload_size = session->http_request.body_length;
/*
* Admissions Control State

@ -9,19 +9,18 @@
const char *sandbox_state_labels[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = "Uninitialized",
[SANDBOX_ALLOCATED] = "Allocated",
[SANDBOX_INITIALIZED] = "Initialized",
[SANDBOX_RUNNABLE] = "Runnable",
[SANDBOX_INTERRUPTED] = "Interrupted",
[SANDBOX_PREEMPTED] = "Preempted",
[SANDBOX_RUNNING_SYS] = "Running Sys",
[SANDBOX_RUNNING_USER] = "Running User",
[SANDBOX_ASLEEP] = "Asleep",
[SANDBOX_RETURNED] = "Returned",
[SANDBOX_COMPLETE] = "Complete",
[SANDBOX_ERROR] = "Error"
};
[SANDBOX_UNINITIALIZED] = "Uninitialized",
[SANDBOX_ALLOCATED] = "Allocated",
[SANDBOX_INITIALIZED] = "Initialized",
[SANDBOX_RUNNABLE] = "Runnable",
[SANDBOX_INTERRUPTED] = "Interrupted",
[SANDBOX_PREEMPTED] = "Preempted",
[SANDBOX_RUNNING_SYS] = "Running Sys",
[SANDBOX_RUNNING_USER] = "Running User",
[SANDBOX_ASLEEP] = "Asleep",
[SANDBOX_RETURNED] = "Returned",
[SANDBOX_COMPLETE] = "Complete",
[SANDBOX_ERROR] = "Error"};
#ifdef SANDBOX_STATE_TOTALS
_Atomic uint32_t sandbox_state_totals[SANDBOX_STATE_COUNT];

@ -9,33 +9,31 @@ sandbox_state_transition_hook_default(struct sandbox *sandbox)
/* Called while nonpreemptable */
sandbox_state_transition_hook_t sandbox_state_transition_to_hooks[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default
};
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default};
/* Called while nonpreemptable */
sandbox_state_transition_hook_t sandbox_state_transition_from_hooks[SANDBOX_STATE_COUNT] = {
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default
};
[SANDBOX_UNINITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_ALLOCATED] = sandbox_state_transition_hook_default,
[SANDBOX_INITIALIZED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNABLE] = sandbox_state_transition_hook_default,
[SANDBOX_INTERRUPTED] = sandbox_state_transition_hook_default,
[SANDBOX_PREEMPTED] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_SYS] = sandbox_state_transition_hook_default,
[SANDBOX_RUNNING_USER] = sandbox_state_transition_hook_default,
[SANDBOX_ASLEEP] = sandbox_state_transition_hook_default,
[SANDBOX_RETURNED] = sandbox_state_transition_hook_default,
[SANDBOX_COMPLETE] = sandbox_state_transition_hook_default,
[SANDBOX_ERROR] = sandbox_state_transition_hook_default};

@ -1,11 +1,11 @@
#include "sledge_abi.h"
#include "current_sandbox.h"
#include "map.h"
#include "sandbox_set_as_running_sys.h"
#include "sandbox_set_as_running_user.h"
#include "sledge_abi.h"
#include "wasm_memory.h"
#include "wasi.h"
#include "wasi_serdes.h"
#include "wasm_memory.h"
EXPORT void
sledge_abi__wasm_trap_raise(enum sledge_abi__wasm_trap trapno)

@ -1,14 +1,14 @@
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <threads.h>
#include <unistd.h>
#include <ucontext.h>
#include <unistd.h>
#include "arch/context.h"
#include "current_sandbox.h"
@ -18,8 +18,8 @@
#include "module.h"
#include "panic.h"
#include "runtime.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_set_as_interrupted.h"
#include "sandbox_set_as_running_user.h"
#include "sandbox_types.h"
#include "scheduler.h"
#include "software_interrupt.h"
@ -269,7 +269,7 @@ software_interrupt_initialize(void)
sigaddset(&signal_action.sa_mask, SIGFPE);
sigaddset(&signal_action.sa_mask, SIGSEGV);
const int supported_signals[] = { SIGALRM, SIGUSR1, SIGFPE, SIGSEGV };
const int supported_signals[] = {SIGALRM, SIGUSR1, SIGFPE, SIGSEGV};
const size_t supported_signals_len = 4;
for (int i = 0; i < supported_signals_len; i++) {

@ -1,4 +1,5 @@
#include "tenant.h"
#include "current_sandbox.h"
#include "tenant_functions.h"
/**
@ -23,3 +24,50 @@ err:
rc = -1;
goto done;
}
#ifdef EXECUTION_REGRESSION
void
tenant_preprocess(struct http_session *session)
{
/* No tenant preprocessing if the wasm module not provided by the tenant */
if (session->route->module_proprocess == NULL) goto done;
const uint64_t start = __getcycles();
/* Tenant Pre-processing - Extract other useful parameters */
struct sandbox *pre_sandbox = sandbox_alloc(session->route->module_proprocess, session, session->route,
session->tenant, 1);
if (sandbox_prepare_execution_environment(pre_sandbox)) panic("pre_sandbox environment setup failed");
pre_sandbox->state = SANDBOX_RUNNING_SYS;
assert(current_sandbox_get() == NULL);
current_sandbox_set(pre_sandbox);
current_sandbox_start();
auto_buf_flush(&session->response_body);
char *endptr;
long num = strtol(session->response_body.data, &endptr, 10);
if (endptr == session->response_body.data) {
printf("No digits were found\n");
} else if (*endptr != '\0' && *endptr != '\n') {
printf("Further characters after number: %s\n", endptr);
} else if ((errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) || (errno != 0 && num == 0)) {
perror("strtol");
} else {
session->regression_param = num;
}
session->http_request.cursor = 0;
pre_sandbox->http = NULL;
pre_sandbox->state = SANDBOX_COMPLETE;
auto_buf_deinit(&session->response_body);
current_sandbox_set(NULL);
sandbox_free_linear_memory(pre_sandbox);
sandbox_free(pre_sandbox);
const uint64_t end = __getcycles();
session->preprocessing_duration = end - start;
done:
session->did_preprocessing = true;
}
#endif

@ -1,14 +1,14 @@
#include <errno.h>
#include "panic.h"
#include "runtime.h"
#include "tenant.h"
#include "panic.h"
/*******************
* Tenant Database *
******************/
struct tenant *tenant_database[RUNTIME_MAX_TENANT_COUNT] = { NULL };
struct tenant *tenant_database[RUNTIME_MAX_TENANT_COUNT] = {NULL};
size_t tenant_database_count = 0;
/**

@ -1,8 +1,8 @@
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <threads.h>
@ -12,11 +12,11 @@
#include "local_runqueue_list.h"
#include "local_runqueue_minheap.h"
#include "panic.h"
#include "priority_queue.h"
#include "runtime.h"
#include "scheduler.h"
#include "worker_thread.h"
#include "tenant_functions.h"
#include "priority_queue.h"
#include "worker_thread.h"
/***************************
* Worker Thread State *

@ -63,7 +63,7 @@ run_perf_tests() {
else
image=$same_image
fi
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m GET -D "${image}" "http://${hostname}:10000${route[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" 2> /dev/null &
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m POST -D "${image}" "http://${hostname}:10000${route[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" 2> /dev/null &
done
pids=$(pgrep hey | tr '\n' ' ')
[[ -n $pids ]] && wait -f $pids

@ -2,8 +2,6 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/rand",

@ -68,7 +68,7 @@ run_perf_tests() {
done
((batch_id++))
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m GET -D "./${workload}.dat" "http://${hostname}:10000${path[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" &
hey -disable-compression -disable-keepalive -disable-redirects -n $batch_size -c 1 -cpus 1 -t 0 -o csv -m POST -D "./${workload}.dat" "http://${hostname}:10000${path[$workload]}" > "$results_directory/${workload}_${batch_id}.csv" &
done
pids=$(pgrep hey | tr '\n' ' ')
[[ -n $pids ]] && wait -f $pids

@ -2,8 +2,6 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/ekf_first_iter",

@ -2,8 +2,6 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/ekf",

@ -40,14 +40,16 @@ declare -gr SANDBOX_ROUTE_FIELD=3
declare -gr SANDBOX_CPU_FREQ_FIELD=20
declare -gr SANDBOX_RESPONSE_CODE_FIELD=21
declare -gr SANDBOX_GUARANTEE_TYPE_FIELD=22
declare -gr SANDBOX_PAYLOAD_SIZE=23
# HTTP Session Perf Log Globals:
declare -ga HTTP_METRICS=(http_receive http_sent http_total)
declare -ga HTTP_METRICS=(http_receive http_sent http_total http_preprocess)
declare -gA HTTP_METRICS_FIELDS=(
[http_receive]=6
[http_sent]=7
[http_total]=8
[http_preprocess]=9
)
declare -gr HTTP_TENANT_NAME_FIELD=1
declare -gr HTTP_ROUTE_FIELD=2
declare -gr HTTP_CPU_FREQ_FIELD=9
declare -gr HTTP_CPU_FREQ_FIELD=10

@ -7,20 +7,11 @@ jq_admin_spec() {
jq ". + {\
\"name\": \"Admin\",\
\"port\": 55555,\
\"replenishment-period-us\": 0,\
\"max-budget-us\": 0,\
\"reservation-percentile\": 0,\
\"routes\": [\
.routes[] + {\
\"route\": \"/admin\",\
\"admissions-percentile\": 50,\
\"expected-execution-us\": 1000,\
\"relative-deadline-us\": 10000},\
\"route\": \"/admin\"},\
.routes[] + {\
\"route\": \"/terminator\",\
\"admissions-percentile\": 50,\
\"expected-execution-us\": 1000,\
\"relative-deadline-us\": 10000}\
\"route\": \"/terminator\"}\
]\
}" < "./template.json" > "./result_admin.json"
}
@ -33,17 +24,22 @@ generate_spec_json() {
local jq_str
local tenant=$(printf "%s-%03d" "${TENANT_IDS[$t_idx]}" "$var")
local port=${ports[$tenant]}
local repl_period=${repl_periods[$tenant]}
local budget=${max_budgets[$tenant]}
local reservation=${reservations[$tenant]}
jq_str=". + {
\"name\": \"$tenant\",\
\"port\": $port,\
\"replenishment-period-us\": $repl_period,\
\"max-budget-us\": $budget,\
\"reservation-percentile\": $reservation,\
\"routes\": ["
\"port\": $port"
if [ -n "$MTDS_REPL_PERIODS_us" ]; then
repl_period=${repl_periods[$tenant]}
budget=${max_budgets[$tenant]}
jq_str+=",\"replenishment-period-us\": $repl_period,\"max-budget-us\": $budget"
fi
if [ -n "$MTDBF_RESERVATIONS_p" ]; then
reservation=${reservations[$tenant]}
jq_str+=",\"reservation-percentile\": $reservation"
fi
jq_str+=",\"routes\": ["
local t_routes
IFS=' ' read -r -a t_routes <<< ${ROUTES[$t_idx]}
@ -53,17 +49,34 @@ generate_spec_json() {
local workload="$tenant-$route"
local wasm_path=${wasm_paths[$workload]}
local resp_content_type=${resp_content_types[$workload]}
local expected=${expected_execs[$workload]}
local deadline=${deadlines[$workload]}
jq_str+=".routes[] + {\
\"route\": \"/$route\",\
\"path\": \"$wasm_path\",\
\"admissions-percentile\": $ESTIMATIONS_PERCENTILE,\
\"expected-execution-us\": $expected,\
\"relative-deadline-us\": $deadline,\
\"http-resp-content-type\": \"$resp_content_type\"}"
\"http-resp-content-type\": \"$resp_content_type\""
if [ -n "$PREPROCESS_WASM_PATHS" ]; then
local preprocess_wasm_path=${preprocess_wasm_paths[$workload]}
local model_bias=${model_biases[$workload]}
local model_scale=${model_scales[$workload]}
local model_num_of_param=${model_num_of_params[$workload]}
local model_beta1=${model_beta1s[$workload]}
local model_beta2=${model_beta2s[$workload]}
jq_str+=",
\"path_preprocess\": \"$preprocess_wasm_path\",\
\"model-bias\": $model_bias,\
\"model-scale\": $model_scale,\
\"model-num-of-param\": $model_num_of_param,\
\"model-beta1\": $model_beta1,\
\"model-beta2\": $model_beta2"
fi
jq_str+="}"
if [ "$index" != $((${#t_routes[@]}-1)) ]; then
jq_str+=","
fi
@ -74,7 +87,7 @@ generate_spec_json() {
done
done
jq_admin_spec
if [ "$CLIENT_TERMINATE_SERVER" == true ]; then jq_admin_spec; fi
# Merges all of the multiple specs for a single module
jq -s '. | sort_by(.name)' ./result_*.json > "./spec.json"

@ -22,6 +22,37 @@ if ! command -v hey > /dev/null; then
fi
fi
if ! command -v gnuplot > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y gnuplot
else
sudo apt update
sudo apt install -y gnuplot
fi
fi
if ! command -v jq > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y jq
else
sudo apt update
sudo apt install -y jq
fi
fi
if ! command -v htop > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y htop
else
sudo apt update
sudo apt install -y htop
fi
fi
if ! command -v loadtest > /dev/null; then
if ! command -v npm > /dev/null; then
# if [[ $(whoami) == "root" ]]; then
@ -33,6 +64,7 @@ if ! command -v loadtest > /dev/null; then
# fi
# installs NVM (Node Version Manager)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
sleep 5
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
@ -63,37 +95,6 @@ if ! command -v loadtest > /dev/null; then
popd
fi
if ! command -v gnuplot > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y gnuplot
else
sudo apt update
sudo apt install -y gnuplot
fi
fi
if ! command -v jq > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y jq
else
sudo apt update
sudo apt install -y jq
fi
fi
if ! command -v htop > /dev/null; then
if [[ $(whoami) == "root" ]]; then
apt update
apt install -y htop
else
sudo apt update
sudo apt install -y htop
fi
fi
# For SOD:
# if ! command -v imagemagick > /dev/null; then
# if [ "$(whoami)" == "root" ]; then

@ -151,7 +151,7 @@ process_client_results_hey() {
for workload in "${workloads[@]}"; do
local t_id=${workload_tids[$workload]}
local deadline=${workload_deadlines[$workload]}
local deadline=${deadlines[$workload]}
local var=${workload_vars[$workload]}
# Some requests come back with an "Unsolicited response ..." See issue #185
@ -273,7 +273,8 @@ process_client_results_loadtest() {
# throughput=$(grep "Requests per second" "$results_directory/${workload}.dat" | tr -s ' ' | cut -d ' ' -f 14 | tail -n 1) # throughput of ALL
throughput=$(echo "$total/$duration" | bc)
goodput=$(echo "$all200/$duration" | bc)
printf "%s,%.1f\n" "$var" "$success_rate" >> "$results_directory/throughput_$t_id.csv"
# printf "%s,%.1f\n" "$var" "$success_rate" >> "$results_directory/throughput_$t_id.csv"
printf "%s,%s\n" "$throughput" "$goodput" >> "$results_directory/throughput_$t_id.csv"
# Generate Latency Data
min=$(awk '/Minimum latency/ {sum += $13; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
@ -338,7 +339,7 @@ process_server_results() {
mkdir -p "$results_directory/$workload"
local t_id=${workload_tids[$workload]}
local deadline=${workload_deadlines[$workload]}
local deadline=${deadlines[$workload]}
local var=${workload_vars[$workload]}
for metric in "${SANDBOX_METRICS[@]}"; do
@ -386,8 +387,13 @@ process_server_results() {
END{printf "'"$var"',%3.1f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", (all200*100/NR), NR, ok, all200, total_failed, denied_any, denied_gtd, x_denied_any, x_denied_gtd, mis_dl_glob, mis_dl_local, mis_dl_wb, shed_glob, shed_local, misc, guaranteed, besteffort}
' < "$results_directory/$workload/total_sorted.csv" >> "$results_directory/success_$t_id.csv"
total=$(awk 'END {printf "%d", NR}' "$results_directory/$workload/total_sorted.csv")
ok=$(awk -F, '$2 == 200 && $1 <= '"$deadline"' {ok++} END {printf "%d", ok}' "$results_directory/$workload/total_sorted.csv")
throughput=$(echo "$total/$DURATION_sec" | bc)
goodput=$(echo "$ok/$DURATION_sec" | bc)
# Throughput is calculated on the client side, so ignore the below line
printf "%s,%d\n" "$var" "1" >> "$results_directory/throughput_$t_id.csv"
printf "%s,%s\n" "$throughput" "$goodput" >> "$results_directory/throughput_$t_id.csv"
# Generate Latency Data for csv
percentiles_table_row "$results_directory/$workload/total_sorted.csv" "$results_directory/latency_$t_id.csv" "$var"
@ -477,7 +483,7 @@ experiment_server_post() {
if [[ -f "$__run_sh__base_path/$SLEDGE_SANDBOX_PERF_LOG" ]]; then
mv "$__run_sh__base_path/$SLEDGE_SANDBOX_PERF_LOG" "$results_directory/$SERVER_LOG_FILE"
process_server_results "$results_directory" || return 1
rm "$results_directory/$SLEDGE_SANDBOX_PERF_LOG"
# rm "$results_directory/$SLEDGE_SANDBOX_PERF_LOG"
else
echo "Sandbox Perf Log was set, but $SERVER_LOG_FILE not found!"
fi
@ -487,7 +493,7 @@ experiment_server_post() {
if [[ -f "$__run_sh__base_path/$SLEDGE_HTTP_SESSION_PERF_LOG" ]]; then
mv "$__run_sh__base_path/$SLEDGE_HTTP_SESSION_PERF_LOG" "$results_directory/$SERVER_HTTP_LOG_FILE"
process_server_http_results "$results_directory" || return 1
rm "$results_directory/$SERVER_HTTP_LOG_FILE"
# rm "$results_directory/$SERVER_HTTP_LOG_FILE"
else
echo "HTTP Perf Log was set, but $SERVER_HTTP_LOG_FILE not found!"
fi

@ -9,16 +9,21 @@ declare -A repl_periods=()
declare -A max_budgets=()
declare -A reservations=()
declare -A wasm_paths=()
declare -A preprocess_wasm_paths=()
declare -A expected_execs=()
declare -A deadlines=()
declare -A resp_content_types=()
declare -A model_biases=()
declare -A model_scales=()
declare -A model_num_of_params=()
declare -A model_beta1s=()
declare -A model_beta2s=()
declare -A arg_opts_hey=()
declare -A arg_opts_lt=()
declare -A args=()
declare -A loads=()
declare -a workloads=()
declare -A workload_tids=()
declare -A workload_deadlines=()
declare -A workload_vars=()
assert_run_experiments_args() {
@ -82,6 +87,7 @@ run_init() {
reservations+=([$tenant]=$reservation)
local t_routes r_expected_execs r_deadlines r_arg_opts_hey r_arg_opts_lt r_args r_loads
local r_model_biases r_model_scales r_model_num_of_params r_model_beta1s r_model_beta2s
IFS=' ' read -r -a t_routes <<< "${ROUTES[$t_idx]}"
IFS=' ' read -r -a r_wasm_paths <<< "${WASM_PATHS[$t_idx]}"
@ -89,6 +95,13 @@ run_init() {
IFS=' ' read -r -a r_dl_to_exec_ratios <<< "${DEADLINE_TO_EXEC_RATIOs[$t_idx]}"
IFS=' ' read -r -a r_resp_content_types <<< "${RESP_CONTENT_TYPES[$t_idx]}"
IFS=' ' read -r -a r_preprocess_wasm_paths <<< "${PREPROCESS_WASM_PATHS[$t_idx]}"
IFS=' ' read -r -a r_model_biases <<< "${MODEL_BIASES[$t_idx]}"
IFS=' ' read -r -a r_model_scales <<< "${MODEL_SCALES[$t_idx]}"
IFS=' ' read -r -a r_model_num_of_params <<< "${MODEL_NUM_OF_PARAMS[$t_idx]}"
IFS=' ' read -r -a r_model_beta1s <<< "${MODEL_BETA1S[$t_idx]}"
IFS=' ' read -r -a r_model_beta2s <<< "${MODEL_BETA2S[$t_idx]}"
IFS=' ' read -r -a r_arg_opts_hey <<< "${ARG_OPTS_HEY[$t_idx]}"
IFS=' ' read -r -a r_arg_opts_lt <<< "${ARG_OPTS_LT[$t_idx]}"
IFS=' ' read -r -a r_args <<< "${ARGS[$t_idx]}"
@ -98,10 +111,15 @@ run_init() {
local route=${t_routes[$r_idx]}
local wasm_path=${r_wasm_paths[$r_idx]}
local expected=$(load_value "${r_expected_execs[$r_idx]}" "$var")
# local deadline=${r_deadlines[$r_idx]}
local dl_to_exec_ratio=${r_dl_to_exec_ratios[$r_idx]}
local deadline=$((expected*dl_to_exec_ratio/100))
local resp_content_type=${r_resp_content_types[$r_idx]}
local preprocess_wasm_path=${r_preprocess_wasm_paths[$r_idx]}
local model_bias=${r_model_biases[$r_idx]}
local model_scale=${r_model_scales[$r_idx]}
local model_num_of_param=${r_model_num_of_params[$r_idx]}
local model_beta1=${r_model_beta1s[$r_idx]}
local model_beta2=${r_model_beta2s[$r_idx]}
local arg_opt_hey=${r_arg_opts_hey[$r_idx]}
local arg_opt_lt=${r_arg_opts_lt[$r_idx]}
local arg=$(load_value "${r_args[$r_idx]}" "$var")
@ -112,13 +130,18 @@ run_init() {
expected_execs+=([$workload]=$expected)
deadlines+=([$workload]=$deadline)
resp_content_types+=([$workload]=$resp_content_type)
preprocess_wasm_paths+=([$workload]=$preprocess_wasm_path)
model_biases+=([$workload]=$model_bias)
model_scales+=([$workload]=$model_scale)
model_num_of_params+=([$workload]=$model_num_of_param)
model_beta1s+=([$workload]=$model_beta1)
model_beta2s+=([$workload]=$model_beta2)
arg_opts_hey+=([$workload]=$arg_opt_hey)
arg_opts_lt+=([$workload]=$arg_opt_lt)
args+=([$workload]=$arg)
loads+=([$workload]=$load)
workloads+=("$workload")
workload_tids+=([$workload]=$tenant_id)
workload_deadlines+=([$workload]=$deadline)
workload_vars+=([$workload]=$var)
done
done

@ -26,23 +26,23 @@ profile() {
local -r results_directory="$2"
# ekf
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m GET -D "./ekf/initial_state.dat" "http://${hostname}:10000/ekf" > /dev/null
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m POST -D "./ekf/initial_state.dat" "http://${hostname}:10000/ekf" > /dev/null
printf "[ekf: OK]\n"
# Resize
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m GET -D "./resize/shrinking_man_large.jpg" "http://${hostname}:10000/resize" > /dev/null
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m POST -D "./resize/shrinking_man_large.jpg" "http://${hostname}:10000/resize" > /dev/null
printf "[resize: OK]\n"
# lpd
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m GET -D "./lpd/Cars0.png" "http://${hostname}:10000/lpd" > /dev/null
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m POST -D "./lpd/Cars0.png" "http://${hostname}:10000/lpd" > /dev/null
printf "[lpd: OK]\n"
# gocr
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m GET -D "./gocr/hyde.pnm" "http://${hostname}:10000/gocr" > /dev/null
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m POST -D "./gocr/hyde.pnm" "http://${hostname}:10000/gocr" > /dev/null
printf "[gocr: OK]\n"
# cifar10
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m GET -D "./cifar10/airplane1.bmp" "http://${hostname}:10000/cifar10" > /dev/null
hey -disable-compression -disable-keepalive -disable-redirects -n 256 -c 1 -cpus 1 -t 0 -o csv -m POST -D "./cifar10/airplane1.bmp" "http://${hostname}:10000/cifar10" > /dev/null
printf "[cifar10: OK]\n"
}

@ -2,8 +2,6 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/ekf",

@ -13,6 +13,7 @@ export SLEDGE_HTTP_SESSION_PERF_LOG=http_perf.log
# export EXTRA_EXEC_PERCENTILE=10
# The global configs for the scripts
declare -r ADMIN_ACCESS=false
declare -r CLIENT_TERMINATE_SERVER=false
declare -r DURATION_sec=30
declare -r ESTIMATIONS_PERCENTILE=60

@ -1,44 +1,19 @@
[
{
"name": "Admin",
"port": 55555,
"replenishment-period-us": 0,
"max-budget-us": 0,
"reservation-percentile": 0,
"routes": [
{
"route": "/admin",
"path": "fibonacci.wasm.so",
"admissions-percentile": 50,
"expected-execution-us": 1000,
"relative-deadline-us": 10000,
"http-resp-content-type": "text/plain"
},
{
"route": "/terminator",
"path": "fibonacci.wasm.so",
"admissions-percentile": 50,
"expected-execution-us": 1000,
"relative-deadline-us": 10000,
"http-resp-content-type": "text/plain"
}
]
},
{
"name": "cmu-000",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"reservation-percentile": 0,
"routes": [
{
"route": "/depth_to_xyz",
"path": "depth_to_xyz.wasm.so",
"admissions-percentile": 60,
"expected-execution-us": 950000,
"relative-deadline-us": 4750000,
"relative-deadline-us": 0,
"http-resp-content-type": "image/png"
}
]
],
"replenishment-period-us": 0,
"max-budget-us": 0,
"reservation-percentile": 0
}
]

@ -1,9 +1,6 @@
{
"name": "tenant",
"port": 0,
"replenishment-period-us": 0,
"max-budget-us": 0,
"reservation-percentile": 0,
"routes": [
{
"route": "/route",

@ -2,8 +2,6 @@
{
"name": "gwu",
"port": 10000,
"replenishment-period-us": 0,
"max-budget-us": 0,
"routes": [
{
"route": "/empty",

@ -44,7 +44,7 @@ client-preempt:
(http :10010/fib2?40 &); http :10010/fib?10
client-fib10-multi:
hey -z ${DURATION_SEC}s -cpus 4 -c 100 -t 0 -o csv -m GET -d "10\n" "http://${HOSTNAME}:10020/fib"
hey -z ${DURATION_SEC}s -cpus 4 -c 100 -t 0 -o csv -m POST -d "10\n" "http://${HOSTNAME}:10020/fib"
client-fib40-multi:
hey -z ${DURATION_SEC}s -cpus 4 -c 100 -t 0 -o csv -m GET -d "40\n" "http://${HOSTNAME}:10010/fib2"
hey -z ${DURATION_SEC}s -cpus 4 -c 100 -t 0 -o csv -m POST -d "40\n" "http://${HOSTNAME}:10010/fib2"

@ -50,13 +50,13 @@ run_samples() {
local -ir PERF_WINDOW_CAPACITY
printf "Running Samples: "
hey -disable-compression -disable-keepalive -disable-redirects -n "$PERF_WINDOW_CAPACITY" -c "$PERF_WINDOW_CAPACITY" -cpus 3 -t 0 -o csv -m GET -d "40\n" "http://${hostname}:10010/fib2" 1> /dev/null 2> /dev/null || {
hey -disable-compression -disable-keepalive -disable-redirects -n "$PERF_WINDOW_CAPACITY" -c "$PERF_WINDOW_CAPACITY" -cpus 3 -t 0 -o csv -m POST -d "40\n" "http://${hostname}:10010/fib2" 1> /dev/null 2> /dev/null || {
printf "[ERR]\n"
panic "fib40 samples failed with $?"
return 1
}
hey -disable-compression -disable-keepalive -disable-redirects -n "$PERF_WINDOW_CAPACITY" -c "$PERF_WINDOW_CAPACITY" -cpus 3 -t 0 -o csv -m GET -d "10\n" "http://${hostname}:100010/fib" 1> /dev/null 2> /dev/null || {
hey -disable-compression -disable-keepalive -disable-redirects -n "$PERF_WINDOW_CAPACITY" -c "$PERF_WINDOW_CAPACITY" -cpus 3 -t 0 -o csv -m POST -d "10\n" "http://${hostname}:100010/fib" 1> /dev/null 2> /dev/null || {
printf "[ERR]\n"
panic "fib10 samples failed with $?"
return 1
@ -94,7 +94,7 @@ run_experiments() {
# Run each separately
printf "\tfib40: "
hey -disable-compression -disable-keepalive -disable-redirects -z ${duration_sec}s -cpus 4 -c 100 -t 0 -o csv -m GET -d "40\n" "http://$hostname:10010/fib2" > "$results_directory/fib40.csv" 2> /dev/null || {
hey -disable-compression -disable-keepalive -disable-redirects -z ${duration_sec}s -cpus 4 -c 100 -t 0 -o csv -m POST -d "40\n" "http://$hostname:10010/fib2" > "$results_directory/fib40.csv" 2> /dev/null || {
printf "[ERR]\n"
panic "fib40 failed"
return 1
@ -107,7 +107,7 @@ run_experiments() {
printf "[OK]\n"
printf "\tfib10: "
hey -disable-compression -disable-keepalive -disable-redirects -z ${duration_sec}s -cpus 4 -c 100 -t 0 -o csv -m GET -d "10\n" "http://$hostname:10010/fib" > "$results_directory/fib10.csv" 2> /dev/null || {
hey -disable-compression -disable-keepalive -disable-redirects -z ${duration_sec}s -cpus 4 -c 100 -t 0 -o csv -m POST -d "10\n" "http://$hostname:10010/fib" > "$results_directory/fib10.csv" 2> /dev/null || {
printf "[ERR]\n"
panic "fib10 failed"
return 1
@ -125,12 +125,12 @@ run_experiments() {
local fib40_con_PID
local fib10_con_PID
hey -disable-compression -disable-keepalive -disable-redirects -z $((duration_sec + 2 * offset))s -cpus 2 -c 100 -t 0 -o csv -m GET -d "40\n" "http://${hostname}:10010/fib2" > "$results_directory/fib40_con.csv" 2> /dev/null &
hey -disable-compression -disable-keepalive -disable-redirects -z $((duration_sec + 2 * offset))s -cpus 2 -c 100 -t 0 -o csv -m POST -d "40\n" "http://${hostname}:10010/fib2" > "$results_directory/fib40_con.csv" 2> /dev/null &
fib40_con_PID="$!"
sleep $offset
hey -disable-compression -disable-keepalive -disable-redirects -z "${duration_sec}s" -cpus 2 -c 100 -t 0 -o csv -m GET -d "10\n" "http://${hostname}:10010/fib" > "$results_directory/fib10_con.csv" 2> /dev/null &
hey -disable-compression -disable-keepalive -disable-redirects -z "${duration_sec}s" -cpus 2 -c 100 -t 0 -o csv -m POST -d "10\n" "http://${hostname}:10010/fib" > "$results_directory/fib10_con.csv" 2> /dev/null &
fib10_con_PID="$!"
wait -f "$fib10_con_PID" || {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save