Compare commits
20 Commits
worker_gen
...
master
Author | SHA1 | Date |
---|---|---|
|
01acb468de | 1 year ago |
|
693e633164 | 1 year ago |
|
0f758a7602 | 1 year ago |
|
7a534581c5 | 1 year ago |
|
8f1ea67df9 | 1 year ago |
|
6b0ba99e86 | 1 year ago |
|
4ae8b02413 | 1 year ago |
|
de22264f4d | 2 years ago |
|
bfc842924e | 2 years ago |
|
9f465e01fe | 2 years ago |
|
22860ba0d1 | 2 years ago |
|
4e1f67929e | 2 years ago |
|
23639915c4 | 2 years ago |
|
b85e13fb5f | 2 years ago |
|
ba8818e4f8 | 2 years ago |
|
90f9987c82 | 2 years ago |
|
8d1ba3d9b0 | 2 years ago |
|
5e2558048a | 3 years ago |
|
562e5d8623 | 3 years ago |
|
bc2c52165a | 3 years ago |
@ -1,24 +1,23 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"includePath": [
|
||||
"/usr/include/",
|
||||
"${workspaceFolder}/runtime/include/",
|
||||
"${workspaceFolder}/runtime/thirdparty/ck/include/",
|
||||
"${workspaceFolder}/runtime/thirdparty/http-parser/",
|
||||
"${workspaceFolder}/runtime/thirdparty/jsmn/",
|
||||
"${workspaceFolder}/awsm/runtime/libc/wasi/include/",
|
||||
"${workspaceFolder}/libsledge/include"
|
||||
],
|
||||
"defines": [
|
||||
"x86_64",
|
||||
"_GNU_SOURCE"
|
||||
],
|
||||
"cStandard": "c17",
|
||||
"compilerPath": "/usr/bin/clang"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"intelliSenseMode": "clang-x64",
|
||||
"includePath": [
|
||||
"/usr/include/",
|
||||
"${workspaceFolder}/runtime/include/",
|
||||
"${workspaceFolder}/runtime/thirdparty/ck/include/",
|
||||
"${workspaceFolder}/runtime/thirdparty/http-parser/",
|
||||
"${workspaceFolder}/runtime/thirdparty/jsmn/",
|
||||
"${workspaceFolder}/awsm/runtime/libc/wasi/include/",
|
||||
"${workspaceFolder}/libsledge/include"
|
||||
],
|
||||
"defines": [
|
||||
"x86_64",
|
||||
"_GNU_SOURCE"
|
||||
],
|
||||
"cStandard": "c17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 69c8b6116664d65a851cc459601bef6af3caeaea
|
||||
Subproject commit 272fcf42b6559ccb5c5213eb78edfc0f703520ab
|
@ -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);
|
@ -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->regression_param};
|
||||
|
||||
/* 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,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;
|
||||
};
|
||||
|
@ -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
|
||||
}
|
@ -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
|
@ -0,0 +1,528 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC1091,SC2034,SC2153,SC2154,SC2155
|
||||
|
||||
# This experiment is intended to document how the level of concurrent requests influence the latency, throughput, and success rate
|
||||
# Success - The percentage of requests that complete by their deadlines
|
||||
# Throughput - The mean number of successful requests per second
|
||||
# Latency - the rount-trip resonse time (us) of successful requests at the p50, p90, p99, and p100 percentiles
|
||||
|
||||
# Add bash_libraries directory to path
|
||||
__run_sh__base_path="$(dirname "$(realpath --logical "$0")")"
|
||||
# __run_sh__base_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
|
||||
# __run_sh__bash_libraries_relative_path="../bash_libraries"
|
||||
__run_sh__bash_libraries_absolute_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
|
||||
export PATH="$__run_sh__bash_libraries_absolute_path:$PATH"
|
||||
|
||||
source csv_to_dat.sh || exit 1
|
||||
source framework.sh || exit 1
|
||||
source generate_gnuplots.sh || exit 1
|
||||
source get_result_count.sh || exit 1
|
||||
source panic.sh || exit 1
|
||||
source path_join.sh || exit 1
|
||||
source percentiles_table.sh || exit 1
|
||||
source experiment_globals.sh || exit 1
|
||||
source multi_tenancy_init.sh || exit 1
|
||||
source generate_spec_json.sh || exit 1
|
||||
|
||||
validate_dependencies hey loadtest gnuplot jq
|
||||
|
||||
# Execute the experiments concurrently
|
||||
run_experiments() {
|
||||
assert_run_experiments_args "$@"
|
||||
|
||||
local -r hostname="$1"
|
||||
local -r results_directory="$2"
|
||||
local -r loadgen="$3"
|
||||
|
||||
printf "Running Experiments with %s\n" "$loadgen"
|
||||
|
||||
for var in "${VARYING[@]}"; do
|
||||
for t_idx in "${!TENANT_IDS[@]}"; do
|
||||
local tenant_id=${TENANT_IDS[$t_idx]}
|
||||
local tenant=$(printf "%s-%03d" "$tenant_id" "$var")
|
||||
local port=${ports[$tenant]}
|
||||
|
||||
local t_routes
|
||||
IFS=' ' read -r -a t_routes <<< "${ROUTES[$t_idx]}"
|
||||
|
||||
for index in "${!t_routes[@]}"; do
|
||||
local route=${t_routes[$index]}
|
||||
local workload="$tenant-$route"
|
||||
local expected=${expected_execs[$workload]}
|
||||
local deadline=${deadlines[$workload]}
|
||||
local arg=${args[$workload]}
|
||||
# local con=${concurrencies[$workload]}
|
||||
# local rps=${rpss[$workload]}
|
||||
local load=${loads[$workload]}
|
||||
|
||||
local pid
|
||||
local -a pids # Run concurrently
|
||||
local -A pid_workloads # Run concurrently
|
||||
|
||||
# Cast the result to int for HEY (Loadtest is okay floats, HEY is not)
|
||||
if [ "$loadgen" = "hey" ]; then
|
||||
local con=$((load * NWORKERS * deadline / expected / 100))
|
||||
if [ "$con" = 0 ]; then con=1; fi
|
||||
# printf -v con %.0f "$con"
|
||||
echo "CON set for $workload" : "$con"
|
||||
local arg_opt_hey=${arg_opts_hey[$workload]}
|
||||
hey -H "Expect: " $HEY_OPTS -z "$DURATION_sec"s -c "$con" -t 0 -o csv -m POST "$arg_opt_hey" "$arg" "http://${hostname}:$port/$route" > "$results_directory/$workload.csv" 2> "$results_directory/$workload-err.dat" &
|
||||
elif [ "$loadgen" = "loadtest" ]; then
|
||||
local con=1 #$((NWORKERS * deadline / expected))
|
||||
local rps=$(echo "scale=2; x = $load * $NWORKERS * 1000000 / $expected / 100; x" | bc)
|
||||
# if [ "$(echo "$rps > $NWORKERS" | bc)" -eq 1 ]; then con=$NWORKERS; fi
|
||||
echo "CON set for $workload" : "$con"
|
||||
echo "RPS set for $workload" : "$rps"
|
||||
local arg_opt_lt=${arg_opts_lt[$workload]}
|
||||
|
||||
[ "$LOADTEST_LOG_RANDOM" = true ] && lograndom=--lograndom
|
||||
if [ "$LOADTEST_REQUEST_TIMEOUT" = true ]; then
|
||||
deadline_ms=$((deadline/1000 + 1))
|
||||
echo "Timeout set for $workload" : "$deadline_ms"
|
||||
req_timeout="-d $deadline_ms"
|
||||
fi
|
||||
[ "$NUCLIO_MODE_ENABLED" = true ] && keep_alive=-k
|
||||
|
||||
step=2500
|
||||
it=1
|
||||
while (( $(bc <<< "$rps > $step") )); do
|
||||
echo " Loadtest #$it: rps of $step/$rps"
|
||||
# shellcheck disable=SC2086
|
||||
loadtest -H "Expect: " -t $DURATION_sec -c $con --rps $step $arg_opt_lt $arg $req_timeout $lograndom $keep_alive "http://${hostname}:${port}/$route" >> "$results_directory/$workload.dat" 2>> "$results_directory/$workload-err.dat" &
|
||||
rps=$(bc <<< "$rps - $step")
|
||||
pid="$!"
|
||||
pids+=("$pid")
|
||||
pid_workloads+=([$pid]="$workload-step-$it")
|
||||
((it++))
|
||||
done
|
||||
|
||||
echo " Loadtest #$it: rps of $rps (last)"
|
||||
# shellcheck disable=SC2086
|
||||
loadtest -H "Expect: " -t $DURATION_sec -c $con --rps $rps $arg_opt_lt $arg $req_timeout $lograndom $keep_alive "http://${hostname}:${port}/$route" >> "$results_directory/$workload.dat" 2>> "$results_directory/$workload-err.dat" &
|
||||
fi
|
||||
pid="$!"
|
||||
pids+=("$pid")
|
||||
pid_workloads+=([$pid]=$workload)
|
||||
done
|
||||
done
|
||||
|
||||
for ((i=${#pids[@]}-1; i>=0; i--)); do
|
||||
local pid=${pids[$i]}
|
||||
local pid_workload=${pid_workloads[$pid]}
|
||||
wait -f "$pid" || {
|
||||
printf "\t%s: [ERR]\n" "$pid_workload"
|
||||
panic "failed to wait -f $pid"
|
||||
return 1
|
||||
}
|
||||
[ "$loadgen" = "hey" ] && (get_result_count "$results_directory/$pid_workload.csv" || {
|
||||
printf "\t%s: [ERR]\n" "$pid_workload"
|
||||
panic "$pid_workload has zero requests."
|
||||
return 1
|
||||
})
|
||||
printf "\t%s: [OK]\n" "$pid_workload"
|
||||
done
|
||||
|
||||
unset pids pid_workloads
|
||||
done
|
||||
|
||||
if [ "$CLIENT_TERMINATE_SERVER" == true ]; then
|
||||
printf "Sent a Terminator to the server\n"
|
||||
echo "5" | http "$hostname":55555/terminator &> /dev/null
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Process the experimental results and generate human-friendly results for success rate, throughput, and latency
|
||||
process_client_results_hey() {
|
||||
assert_process_client_results_args "$@"
|
||||
|
||||
local -r results_directory="$1"
|
||||
|
||||
printf "Processing HEY Results: "
|
||||
|
||||
# Write headers to CSVs
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
printf "Workload,Scs%%,TOTAL,ClientScs,All200,AllFail,Deny,MisDL,Shed,MiscErr\n" >> "$results_directory/success_$t_id.csv"
|
||||
printf "Workload,Throughput\n" >> "$results_directory/throughput_$t_id.csv"
|
||||
percentiles_table_header "$results_directory/latency_$t_id.csv" "Workload"
|
||||
done
|
||||
|
||||
for workload in "${workloads[@]}"; do
|
||||
local t_id=${workload_tids[$workload]}
|
||||
local deadline=${deadlines[$workload]}
|
||||
local var=${workload_vars[$workload]}
|
||||
|
||||
# Some requests come back with an "Unsolicited response ..." See issue #185
|
||||
misc_err=$(wc -l < "$results_directory/$workload-err.dat")
|
||||
|
||||
if [ ! -s "$results_directory/$workload-err.dat" ]; then
|
||||
# The error file is empty. So remove it.
|
||||
rm "$results_directory/$workload-err.dat"
|
||||
fi
|
||||
|
||||
# Calculate Success Rate for csv (percent of requests that return 200 within deadline)
|
||||
awk -v misc_err="$misc_err" -F, '
|
||||
$7 == 200 && ($1 * 1000000) <= '"$deadline"' {ok++}
|
||||
$7 == 200 {all200++}
|
||||
$7 != 200 {total_failed++}
|
||||
$7 == 429 {denied++}
|
||||
$7 == 408 {missed_dl++}
|
||||
$7 == 409 {killed++}
|
||||
END{printf "'"$var"',%3.1f,%d,%d,%d,%d,%d,%d,%d,%d\n", (all200*100/(NR-1+misc_err)), (NR-1+misc_err), ok, all200, (total_failed-1+misc_err), denied, missed_dl, killed, misc_err}
|
||||
' < "$results_directory/$workload.csv" >> "$results_directory/success_$t_id.csv"
|
||||
|
||||
# Convert from s to us, and sort
|
||||
awk -F, 'NR > 1 {print ($1 * 1000000)}' < "$results_directory/$workload.csv" \
|
||||
| sort -g > "$results_directory/$workload-response.csv"
|
||||
|
||||
# Filter on 200s, convert from s to us, and sort
|
||||
awk -F, '$7 == 200 {print ($1 * 1000000)}' < "$results_directory/$workload.csv" \
|
||||
| sort -g > "$results_directory/$workload-response-200.csv"
|
||||
|
||||
# Get Number of all entries
|
||||
all=$(wc -l < "$results_directory/$workload-response.csv")
|
||||
((all == 0)) && continue # If all errors, skip line
|
||||
|
||||
# Get Number of 200s
|
||||
oks=$(wc -l < "$results_directory/$workload-response-200.csv")
|
||||
# ((oks == 0)) && continue # If all errors, skip line
|
||||
|
||||
# We determine duration by looking at the timestamp of the last complete request
|
||||
# TODO: Should this instead just use the client-side synthetic DURATION_sec value?
|
||||
duration=$(tail -n1 "$results_directory/$workload.csv" | cut -d, -f8)
|
||||
|
||||
# Throughput is calculated as the mean number of successful requests per second
|
||||
throughput=$(echo "$oks/$duration" | bc)
|
||||
printf "%s,%d\n" "$var" "$throughput" >> "$results_directory/throughput_$t_id.csv"
|
||||
|
||||
# Generate Latency Data for csv
|
||||
percentiles_table_row "$results_directory/$workload-response.csv" "$results_directory/latency_$t_id.csv" "$var"
|
||||
# Delete scratch file used for sorting/counting
|
||||
rm "$results_directory/$workload-response.csv" "$results_directory/$workload-response-200.csv"
|
||||
done
|
||||
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
# Transform csvs to dat files for gnuplot
|
||||
csv_to_dat "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
rm "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
done
|
||||
|
||||
# Generate gnuplots
|
||||
generate_gnuplots "$results_directory" "$__run_sh__base_path" || {
|
||||
printf "[ERR]\n"
|
||||
panic "failed to generate gnuplots"
|
||||
}
|
||||
|
||||
printf "[OK]\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Process the experimental results and generate human-friendly results for success rate, throughput, and latency
|
||||
process_client_results_loadtest() {
|
||||
assert_process_client_results_args "$@"
|
||||
|
||||
local -r results_directory="$1"
|
||||
local sum_of_durations=0
|
||||
|
||||
printf "Processing Loadtest Results: \n"
|
||||
|
||||
# Write headers to CSVs
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
printf "Workload,Scs%%,TOTAL,All200,AllFail,Deny,MisDL,Shed,MiscErr\n" >> "$results_directory/success_$t_id.csv"
|
||||
printf "Workload,Throughput\n" >> "$results_directory/throughput_$t_id.csv"
|
||||
percentiles_table_header "$results_directory/latency_$t_id.csv" "Workload"
|
||||
done
|
||||
|
||||
for workload in "${workloads[@]}"; do
|
||||
local t_id=${workload_tids[$workload]}
|
||||
local var=${workload_vars[$workload]}
|
||||
# local expected=${expected_execs[$workload]}
|
||||
# local load=${loads[$workload]}
|
||||
# local rps=$(echo "scale=2; x = $load * $NWORKERS * 1000000 / $expected / 100; x" | bc)
|
||||
|
||||
if [ ! -s "$results_directory/$workload-err.dat" ]; then
|
||||
# The error file is empty. So remove it.
|
||||
rm "$results_directory/$workload-err.dat"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$results_directory/$workload.dat" ]]; then
|
||||
printf "[ERR]\n"
|
||||
error_msg "Missing $results_directory/$workload.dat"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Get Number of 200s and then calculate Success Rate (percent of requests that return 200)
|
||||
total=$(awk '/Completed requests:/ {sum += $13} END {print sum}' "$results_directory/${workload}.dat")
|
||||
total_failed=$(awk '/Total errors:/ {sum += $13} END {print sum}' "$results_directory/${workload}.dat")
|
||||
denied=$(awk '/429:/ {sum += $12} END {print sum}' "$results_directory/${workload}.dat")
|
||||
missed_dl=$(awk '/408:/ {sum += $12} END {print sum}' "$results_directory/${workload}.dat")
|
||||
killed=$(awk '/409:/ {sum += $12} END {print sum}' "$results_directory/${workload}.dat")
|
||||
misc_err=$(awk '/(-1:|503:)/ {sum += $12} END {print sum}' "$results_directory/${workload}.dat")
|
||||
all200=$((total - total_failed))
|
||||
|
||||
# ((all200 == 0)) && continue # If all errors, skip line
|
||||
success_rate=$(echo "scale=2; $all200*100/$total" | bc)
|
||||
printf "%s,%3.1f,%d,%d,%d,%d,%d,%d,%d\n" "$var" "$success_rate" "$total" "$all200" "$total_failed" "$denied" "$missed_dl" "$killed" "$misc_err" >> "$results_directory/success_$t_id.csv"
|
||||
|
||||
# Throughput is calculated as the mean number of successful requests per second
|
||||
duration=$(awk '/Total time:/ {sum += $13; count++} END {print sum / count}' "$results_directory/${workload}.dat")
|
||||
sum_of_durations=$(echo "scale=2; x = $sum_of_durations+$duration; x" | bc)
|
||||
# printf -v duration %.2f "$duration"
|
||||
# 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,%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")
|
||||
mean=$(awk '/Mean latency:/ {sum += $13; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
|
||||
p50=$(awk '/50%/ {sum += $12; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
|
||||
p90=$(awk '/90%/ {sum += $12; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
|
||||
p99=$(awk '/99%/ {sum += $12; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
|
||||
p100=$(awk '/100%/ {sum += $12; count++} END {print int(sum*1000/count)}' "$results_directory/${workload}.dat")
|
||||
|
||||
printf "%s,%d,%d,%d,%d,%d,%d,%d\n" "$var" "$total" "$min" "$mean" "$p50" "$p90" "$p99" "$p100" >> "$results_directory/latency_$t_id.csv"
|
||||
printf "Workload %20s duration: %.2f sec\n" "$workload" "$duration"
|
||||
done
|
||||
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
# Transform csvs to dat files for gnuplot
|
||||
csv_to_dat "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
rm "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
done
|
||||
|
||||
# Generate gnuplots
|
||||
generate_gnuplots "$results_directory" "$__run_sh__base_path" || {
|
||||
printf "[ERR]\n"
|
||||
panic "failed to generate gnuplots"
|
||||
}
|
||||
|
||||
local ave_duration=$(echo "scale=2; x = $sum_of_durations/${#workloads[@]}; x" | bc)
|
||||
printf "Experiments average duration: %.2f sec\n" "$ave_duration"
|
||||
printf "[OK]\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
process_server_results() {
|
||||
assert_process_server_results_args "$@"
|
||||
|
||||
local -r results_directory="${1:?results_directory not set}"
|
||||
|
||||
printf "Processing Server Results: \n"
|
||||
|
||||
local -r num_of_lines=$(wc -l < "$results_directory/$SERVER_LOG_FILE")
|
||||
if [ "$num_of_lines" == 1 ]; then
|
||||
printf "No results to process! Exiting the script."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Write headers to CSVs
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
printf "Workload,Scs%%,TOTAL,SrvScs,All200,AllFail,DenyBE,DenyG,xDenyBE,xDenyG,MisD_Glb,MisD_Loc,MisD_WB,Shed_Glb,Shed_Loc,Misc,#Guar,#BE\n" >> "$results_directory/success_$t_id.csv"
|
||||
printf "Workload,Throughput\n" >> "$results_directory/throughput_$t_id.csv"
|
||||
percentiles_table_header "$results_directory/latency_$t_id.csv" "Workload"
|
||||
|
||||
# Write headers to CSVs
|
||||
for metric in "${SANDBOX_METRICS[@]}"; do
|
||||
percentiles_table_header "$results_directory/${metric}_$t_id.csv" "Workload"
|
||||
done
|
||||
percentiles_table_header "$results_directory/running_user_200_$t_id.csv" "Workload"
|
||||
# percentiles_table_header "$results_directory/running_user_nonzero_$t_id.csv" "Workload"
|
||||
percentiles_table_header "$results_directory/total_200_$t_id.csv" "Workload"
|
||||
# percentiles_table_header "$results_directory/memalloc_$t_id.csv" "Workload"
|
||||
done
|
||||
|
||||
for workload in "${workloads[@]}"; do
|
||||
mkdir -p "$results_directory/$workload"
|
||||
|
||||
local t_id=${workload_tids[$workload]}
|
||||
local deadline=${deadlines[$workload]}
|
||||
local var=${workload_vars[$workload]}
|
||||
|
||||
for metric in "${SANDBOX_METRICS[@]}"; do
|
||||
awk -F, '
|
||||
{workload = sprintf("%s-%s", $'"$SANDBOX_TENANT_NAME_FIELD"', substr($'"$SANDBOX_ROUTE_FIELD"',2))}
|
||||
workload == "'"$workload"'" {printf("%d,%d,%d\n", $'"${SANDBOX_METRICS_FIELDS[$metric]}"' / $'"$SANDBOX_CPU_FREQ_FIELD"', $'"$SANDBOX_RESPONSE_CODE_FIELD"', $'"$SANDBOX_GUARANTEE_TYPE_FIELD"')}
|
||||
' < "$results_directory/$SERVER_LOG_FILE" | sort -g > "$results_directory/$workload/${metric}_sorted.csv"
|
||||
|
||||
percentiles_table_row "$results_directory/$workload/${metric}_sorted.csv" "$results_directory/${metric}_$t_id.csv" "$workload"
|
||||
|
||||
# Delete scratch file used for sorting/counting
|
||||
# rm "$results_directory/$workload/${metric}_sorted.csv"
|
||||
done
|
||||
|
||||
awk -F, '$2 == 200 {printf("%d,%d\n", $1, $2, $3)}' < "$results_directory/$workload/running_user_sorted.csv" > "$results_directory/$workload/running_user_200_sorted.csv"
|
||||
percentiles_table_row "$results_directory/$workload/running_user_200_sorted.csv" "$results_directory/running_user_200_$t_id.csv" "$workload"
|
||||
# awk -F, '$1 > 0 {printf("%d,%d\n", $1, $2, $3)}' < "$results_directory/$workload/running_user_sorted.csv" > "$results_directory/$workload/running_user_nonzero_sorted.csv"
|
||||
# percentiles_table_row "$results_directory/$workload/running_user_nonzero_sorted.csv" "$results_directory/running_user_nonzero_$t_id.csv" "$workload"
|
||||
awk -F, '$2 == 200 {printf("%d,%d\n", $1, $2, $3)}' < "$results_directory/$workload/total_sorted.csv" > "$results_directory/$workload/total_200_sorted.csv"
|
||||
percentiles_table_row "$results_directory/$workload/total_200_sorted.csv" "$results_directory/total_200_$t_id.csv" "$workload"
|
||||
|
||||
# Memory Allocation
|
||||
# awk -F, '$2 == "'"$workload"'" {printf("%.0f\n", $MEMORY_FIELD)}' < "$results_directory/$SERVER_LOG_FILE" | sort -g > "$results_directory/$workload/memalloc_sorted.csv"
|
||||
|
||||
# percentiles_table_row "$results_directory/$workload/memalloc_sorted.csv" "$results_directory/memalloc_$t_id.csv.csv" "$workload" "%1.0f"
|
||||
|
||||
# Calculate Success Rate for csv (percent of requests that complete), $1 and deadline are both in us, so not converting
|
||||
awk -F, '
|
||||
$2 == 200 && $1 <= '"$deadline"' {ok++}
|
||||
$2 == 200 {all200++}
|
||||
$2 != 200 {total_failed++}
|
||||
$2 == 4290 {denied_any++}
|
||||
$2 == 4291 {denied_gtd++}
|
||||
$2 == 4295 {x_denied_any++}
|
||||
$2 == 4296 {x_denied_gtd++}
|
||||
$2 == 4080 {mis_dl_glob++}
|
||||
$2 == 4081 {mis_dl_local++}
|
||||
$2 == 4082 {mis_dl_wb++}
|
||||
$2 == 4090 {shed_glob++}
|
||||
$2 == 4091 {shed_local++}
|
||||
$2 == 4093 {misc++}
|
||||
$2 == 4293 {misc++}
|
||||
$3 == 1 {guaranteed++}
|
||||
$3 == 2 {besteffort++}
|
||||
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,%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"
|
||||
|
||||
# Delete scratch file used for sorting/counting
|
||||
# rm "$results_directory/$workload/memalloc_sorted.csv"
|
||||
|
||||
# Delete directory
|
||||
# rm -rf "${results_directory:?}/${workload:?}"
|
||||
done
|
||||
|
||||
for t_id in "${TENANT_IDS[@]}"; do
|
||||
for metric in "${SANDBOX_METRICS[@]}"; do
|
||||
csv_to_dat "$results_directory/${metric}_$t_id.csv"
|
||||
rm "$results_directory/${metric}_$t_id.csv"
|
||||
done
|
||||
|
||||
csv_to_dat "$results_directory/running_user_200_$t_id.csv" "$results_directory/total_200_$t_id.csv" # "$results_directory/running_user_nonzero_$t_id.csv"
|
||||
rm "$results_directory/running_user_200_$t_id.csv" "$results_directory/total_200_$t_id.csv" # "$results_directory/running_user_nonzero_$t_id.csv"
|
||||
|
||||
# Transform csvs to dat files for gnuplot
|
||||
# csv_to_dat "$results_directory/memalloc$t_id.csv"
|
||||
csv_to_dat "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
# rm "$results_directory/memalloc$t_id.csv"
|
||||
rm "$results_directory/success_$t_id.csv" "$results_directory/throughput_$t_id.csv" "$results_directory/latency_$t_id.csv"
|
||||
done
|
||||
|
||||
# Generate gnuplots
|
||||
generate_gnuplots "$results_directory" "$__run_sh__base_path" || {
|
||||
printf "[ERR]\n"
|
||||
panic "failed to generate gnuplots"
|
||||
}
|
||||
|
||||
printf "[OK]\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
process_server_http_results() {
|
||||
assert_process_server_results_args "$@"
|
||||
|
||||
local -r results_directory="${1:?results_directory not set}"
|
||||
|
||||
printf "Processing Server HTTP Results: \n"
|
||||
|
||||
local -r num_of_lines=$(wc -l < "$results_directory/$SERVER_HTTP_LOG_FILE")
|
||||
if [ "$num_of_lines" == 1 ]; then
|
||||
printf "No results to process! Exiting the script."
|
||||
return 1
|
||||
fi
|
||||
|
||||
for metric in "${HTTP_METRICS[@]}"; do
|
||||
percentiles_table_header "$results_directory/$metric.csv" "workload"
|
||||
done
|
||||
|
||||
for workload in "${workloads[@]}"; do
|
||||
mkdir -p "$results_directory/$workload"
|
||||
local var=${workload_vars[$workload]}
|
||||
|
||||
for metric in "${HTTP_METRICS[@]}"; do
|
||||
awk -F, '
|
||||
{workload = sprintf("%s-%s", $'"$HTTP_TENANT_NAME_FIELD"', substr($'"$HTTP_ROUTE_FIELD"',2))}
|
||||
workload == "'"$workload"'" {printf("%.1f\n", $'"${HTTP_METRICS_FIELDS[$metric]}"' / $'"$HTTP_CPU_FREQ_FIELD"')}
|
||||
' < "$results_directory/$SERVER_HTTP_LOG_FILE" | sort -g > "$results_directory/$workload/${metric}_sorted.csv"
|
||||
|
||||
percentiles_table_row "$results_directory/$workload/${metric}_sorted.csv" "$results_directory/${metric}.csv" "$var"
|
||||
|
||||
# Delete directory
|
||||
# rm -rf "${results_directory:?}/${workload:?}"
|
||||
done
|
||||
done
|
||||
|
||||
# Transform CSVs to dat files for gnuplot
|
||||
for metric in "${HTTP_METRICS[@]}"; do
|
||||
csv_to_dat "$results_directory/$metric.csv"
|
||||
rm "$results_directory/$metric.csv"
|
||||
done
|
||||
|
||||
printf "[OK]\n"
|
||||
return 0
|
||||
}
|
||||
|
||||
experiment_server_post() {
|
||||
local -r results_directory="$1"
|
||||
|
||||
# Only process data if SLEDGE_SANDBOX_PERF_LOG was set when running sledgert
|
||||
if [[ -n "$SLEDGE_SANDBOX_PERF_LOG" ]]; then
|
||||
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"
|
||||
else
|
||||
echo "Sandbox Perf Log was set, but $SERVER_LOG_FILE not found!"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$SLEDGE_HTTP_SESSION_PERF_LOG" ]]; then
|
||||
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"
|
||||
else
|
||||
echo "HTTP Perf Log was set, but $SERVER_HTTP_LOG_FILE not found!"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Expected Symbol used by the framework
|
||||
experiment_client() {
|
||||
local -r target_hostname="$1"
|
||||
local -r results_directory="$2"
|
||||
local loadgen="$3"
|
||||
|
||||
if [ "$loadgen" = "" ]; then
|
||||
loadgen="hey"
|
||||
echo "No load generator specified. So, defaulting to HEY!"
|
||||
elif [ $loadgen = "lt" ]; then
|
||||
loadgen="loadtest"
|
||||
fi
|
||||
|
||||
#run_samples "$target_hostname" "$loadgen" || return 1
|
||||
run_experiments "$target_hostname" "$results_directory" "$loadgen" || return 1
|
||||
|
||||
if [ "$loadgen" = "hey" ]; then
|
||||
process_client_results_hey "$results_directory" || return 1
|
||||
elif [ "$loadgen" = "loadtest" ]; then
|
||||
process_client_results_loadtest "$results_directory" || return 1
|
||||
else
|
||||
echo "Unknown load generator \"$loadgen\" was entered!"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
# shellcheck shell=bash
|
||||
# shellcheck disable=SC2034,SC2153,SC2154,SC2155
|
||||
if [ -n "$__run_init_sh__" ]; then return; fi
|
||||
__run_init_sh__=$(date)
|
||||
|
||||
# Globals to fill during run_init in run.sh, to use in base and generate_spec
|
||||
declare -A ports=()
|
||||
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_vars=()
|
||||
|
||||
assert_run_experiments_args() {
|
||||
if (($# != 3)); then
|
||||
panic "invalid number of arguments \"$#\""
|
||||
return 1
|
||||
elif [[ -z "$1" ]]; then
|
||||
panic "hostname \"$1\" was empty"
|
||||
return 1
|
||||
elif [[ ! -d "$2" ]]; then
|
||||
panic "directory \"$2\" does not exist"
|
||||
return 1
|
||||
elif [[ -z "$3" ]]; then
|
||||
panic "load gen \"$3\" was empty"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_process_client_results_args() {
|
||||
if (($# != 1)); then
|
||||
error_msg "invalid number of arguments ($#, expected 1)"
|
||||
return 1
|
||||
elif ! [[ -d "$1" ]]; then
|
||||
error_msg "directory $1 does not exist"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_process_server_results_args() {
|
||||
if (($# != 1)); then
|
||||
panic "invalid number of arguments \"$#\""
|
||||
return 1
|
||||
elif [[ ! -d "$1" ]]; then
|
||||
panic "directory \"$1\" does not exist"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
load_value() {
|
||||
local result=$1
|
||||
if [ "$result" = "?" ]; then
|
||||
result=$2
|
||||
fi
|
||||
echo "$result"
|
||||
}
|
||||
|
||||
run_init() {
|
||||
for var in "${VARYING[@]}"; do
|
||||
for t_idx in "${!TENANT_IDS[@]}"; do
|
||||
local tenant_id=${TENANT_IDS[$t_idx]}
|
||||
local tenant=$(printf "%s-%03d" "$tenant_id" "$var")
|
||||
local port=$((INIT_PORTS[t_idx]+var))
|
||||
[ "$NUCLIO_MODE_ENABLED" == true ] && port=${INIT_PORTS[t_idx]}
|
||||
local repl_period=$(load_value "${MTDS_REPL_PERIODS_us[$t_idx]}" "$var")
|
||||
local budget=$(load_value "${MTDS_MAX_BUDGETS_us[$t_idx]}" "$var")
|
||||
local reservation=$(load_value "${MTDBF_RESERVATIONS_p[$t_idx]}" "$var")
|
||||
|
||||
ports+=([$tenant]=$port)
|
||||
repl_periods+=([$tenant]=$repl_period)
|
||||
max_budgets+=([$tenant]=$budget)
|
||||
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]}"
|
||||
IFS=' ' read -r -a r_expected_execs <<< "${EXPECTED_EXEC_TIMES_us[$t_idx]}"
|
||||
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]}"
|
||||
IFS=' ' read -r -a r_loads <<< "${LOADS[$t_idx]}"
|
||||
|
||||
for r_idx in "${!t_routes[@]}"; do
|
||||
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 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")
|
||||
local load=$(load_value "${r_loads[$r_idx]}" "$var")
|
||||
local workload="$tenant-$route"
|
||||
|
||||
wasm_paths+=([$workload]=$wasm_path)
|
||||
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_vars+=([$workload]=$var)
|
||||
done
|
||||
done
|
||||
done
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue