Skip to content
Snippets Groups Projects
Commit 38862262 authored by Benedikt Wetzel's avatar Benedikt Wetzel
Browse files

Merge branch 'master' of git.se.informatik.uni-kiel.de:she/theodolite into...

Merge branch 'master' of git.se.informatik.uni-kiel.de:she/theodolite into 76-introduce-theodolite-helm-chart
parents 3c082b45 d5639df4
No related branches found
No related tags found
1 merge request!60Introduce a Theodolite Helm chart for deploying all dependencies
...@@ -208,6 +208,7 @@ kubectl delete -f theodolite.yaml ...@@ -208,6 +208,7 @@ kubectl delete -f theodolite.yaml
| --prometheus | PROMETHEUS_BASE_URL | Defines where to find the prometheus instance. *Default:* `http://localhost:9090` | | --prometheus | PROMETHEUS_BASE_URL | Defines where to find the prometheus instance. *Default:* `http://localhost:9090` |
| --path | RESULT_PATH | A directory path for the results. Relative to the Execution folder. *Default:* `results` | | --path | RESULT_PATH | A directory path for the results. Relative to the Execution folder. *Default:* `results` |
| --configurations | CONFIGURATIONS | Defines environment variables for the use cases and, thus, enables further configuration options. | | --configurations | CONFIGURATIONS | Defines environment variables for the use cases and, thus, enables further configuration options. |
| --threshold | THRESHOLD | The threshold for the trend slop that the search strategies use to determine that a load could be handled. *Default:* `2000` |
### Domain Restriction ### Domain Restriction
......
...@@ -136,6 +136,11 @@ def benchmark_parser(description): ...@@ -136,6 +136,11 @@ def benchmark_parser(description):
metavar='<strategy>', metavar='<strategy>',
default=os.environ.get('SEARCH_STRATEGY', 'default'), default=os.environ.get('SEARCH_STRATEGY', 'default'),
help='The benchmarking search strategy. Can be set to default, linear-search or binary-search') help='The benchmarking search strategy. Can be set to default, linear-search or binary-search')
parser.add_argument('--threshold',
type=int,
metavar='<threshold>',
default=os.environ.get('THRESHOLD', 2000),
help='The threshold for the trend slop that the search strategies use to determine that a load could be handled')
return parser return parser
......
...@@ -2,7 +2,7 @@ from sklearn.linear_model import LinearRegression ...@@ -2,7 +2,7 @@ from sklearn.linear_model import LinearRegression
import pandas as pd import pandas as pd
import os import os
def compute(directory, filename, warmup_sec, threshold): def compute(directory, filename, warmup_sec):
df = pd.read_csv(os.path.join(directory, filename)) df = pd.read_csv(os.path.join(directory, filename))
input = df input = df
input['sec_start'] = input.loc[0:, 'timestamp'] - input.iloc[0]['timestamp'] input['sec_start'] = input.loc[0:, 'timestamp'] - input.iloc[0]['timestamp']
...@@ -16,4 +16,4 @@ def compute(directory, filename, warmup_sec, threshold): ...@@ -16,4 +16,4 @@ def compute(directory, filename, warmup_sec, threshold):
trend_slope = linear_regressor.coef_[0][0] trend_slope = linear_regressor.coef_[0][0]
return trend_slope return trend_slope
\ No newline at end of file
...@@ -18,5 +18,6 @@ class ExperimentConfig: ...@@ -18,5 +18,6 @@ class ExperimentConfig:
configurations: dict configurations: dict
domain_restriction_strategy: object domain_restriction_strategy: object
search_strategy: object search_strategy: object
threshold: int
subexperiment_executor: object subexperiment_executor: object
subexperiment_evaluator: object subexperiment_evaluator: object
...@@ -7,8 +7,9 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter): ...@@ -7,8 +7,9 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter):
print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[lower]}") print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[lower]}")
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[lower], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[lower], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) success = config.subexperiment_evaluator.execute(subexperiment_config,
if result==1: # successful, the upper neighbor is assumed to also has been successful config.threshold)
if success: # successful, the upper neighbor is assumed to also has been successful
return (lower, subexperiment_counter+1) return (lower, subexperiment_counter+1)
else: # not successful else: # not successful
return (lower+1, subexperiment_counter) return (lower+1, subexperiment_counter)
...@@ -16,15 +17,17 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter): ...@@ -16,15 +17,17 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter):
print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[lower]}") print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[lower]}")
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[lower], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[lower], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) success = config.subexperiment_evaluator.execute(subexperiment_config,
if result==1: # minimal instances found config.threshold)
if success: # minimal instances found
return (lower, subexperiment_counter) return (lower, subexperiment_counter)
else: # not successful, check if lower+1 instances are sufficient else: # not successful, check if lower+1 instances are sufficient
print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[upper]}") print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[upper]}")
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[upper], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[upper], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) success = config.subexperiment_evaluator.execute(subexperiment_config,
if result == 1: # minimal instances found config.threshold)
if success: # minimal instances found
return (upper, subexperiment_counter) return (upper, subexperiment_counter)
else: else:
return (upper+1, subexperiment_counter) return (upper+1, subexperiment_counter)
...@@ -34,8 +37,9 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter): ...@@ -34,8 +37,9 @@ def binary_search(config, dim_value, lower, upper, subexperiment_counter):
print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[mid]}") print(f"Run subexperiment {subexperiment_counter} with config {dim_value} {config.replicass[mid]}")
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[mid], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, config.replicass[mid], config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) success = config.subexperiment_evaluator.execute(subexperiment_config,
if result == 1: # success -> search in (lower, mid-1) config.threshold)
if success: # success -> search in (lower, mid-1)
return binary_search(config, dim_value, lower, mid-1, subexperiment_counter+1) return binary_search(config, dim_value, lower, mid-1, subexperiment_counter+1)
else: # not success -> search in (mid+1, upper) else: # not success -> search in (mid+1, upper)
return binary_search(config, dim_value, mid+1, upper, subexperiment_counter+1) return binary_search(config, dim_value, mid+1, upper, subexperiment_counter+1)
......
...@@ -2,23 +2,30 @@ ...@@ -2,23 +2,30 @@
import os import os
from strategies.strategies.config import SubexperimentConfig from strategies.strategies.config import SubexperimentConfig
def execute(config, dim_value_index, lower_replicas_bound_index, subexperiment_counter): def execute(config, dim_value_index, lower_replicas_bound_index, subexperiment_counter):
new_lower_replicas_bound_index=lower_replicas_bound_index new_lower_replicas_bound_index = lower_replicas_bound_index
new_lower_replicas_bound_found=False new_lower_replicas_bound_found = False
subexperiments_total=len(config.dim_values)*len(config.replicass) subexperiments_total = len(config.dim_values) * len(config.replicass)
while lower_replicas_bound_index < len(config.replicass): while lower_replicas_bound_index < len(config.replicass):
subexperiment_counter+=1 subexperiment_counter += 1
dim_value=config.dim_values[dim_value_index] dim_value = config.dim_values[dim_value_index]
replicas=config.replicass[lower_replicas_bound_index] replicas = config.replicass[lower_replicas_bound_index]
print(f"Run subexperiment {subexperiment_counter} of {subexperiments_total} with dimension value {dim_value} and {replicas} replicas.") print(
f"Run subexperiment {subexperiment_counter} of {subexperiments_total} with dimension value {dim_value} and {replicas} replicas.")
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, replicas, config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(
config.use_case, config.exp_id, subexperiment_counter, dim_value,
replicas, config.partitions, config.cpu_limit, config.memory_limit,
config.execution_minutes, config.prometheus_base_url, config.reset,
config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) == 1 success = config.subexperiment_evaluator.execute(subexperiment_config,
if result == 1 and not new_lower_replicas_bound_found: config.threshold)
if success and not new_lower_replicas_bound_found:
new_lower_replicas_bound_found = True new_lower_replicas_bound_found = True
new_lower_replicas_bound_index = lower_replicas_bound_index new_lower_replicas_bound_index = lower_replicas_bound_index
lower_replicas_bound_index+=1 lower_replicas_bound_index += 1
return (new_lower_replicas_bound_index, subexperiment_counter) return (new_lower_replicas_bound_index, subexperiment_counter)
...@@ -14,8 +14,9 @@ def execute(config, dim_value_index, lower_replicas_bound_index, subexperiment_c ...@@ -14,8 +14,9 @@ def execute(config, dim_value_index, lower_replicas_bound_index, subexperiment_c
subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, replicas, config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations) subexperiment_config = SubexperimentConfig(config.use_case, config.exp_id, subexperiment_counter, dim_value, replicas, config.partitions, config.cpu_limit, config.memory_limit, config.execution_minutes, config.prometheus_base_url, config.reset, config.namespace, config.result_path, config.configurations)
config.subexperiment_executor.execute(subexperiment_config) config.subexperiment_executor.execute(subexperiment_config)
result = config.subexperiment_evaluator.execute(subexperiment_config) success = config.subexperiment_evaluator.execute(subexperiment_config,
if result == 1: config.threshold)
if success:
return (lower_replicas_bound_index, subexperiment_counter) return (lower_replicas_bound_index, subexperiment_counter)
else: else:
lower_replicas_bound_index+=1 lower_replicas_bound_index+=1
......
import lib.trend_slope_computer as trend_slope_computer import lib.trend_slope_computer as trend_slope_computer
import logging import logging
import os import os
import sys
THRESHOLD = 2000
WARMUP_SEC = 60 WARMUP_SEC = 60
def execute(config): def execute(config, threshold):
"""
Check the trend slope of the totallag of the subexperiment if it comes below
the threshold.
:param config: Configuration of the subexperiment.
:param threshold: The threshold the trendslope need to come below.
"""
cwd = f'{os.getcwd()}/{config.result_path}' cwd = f'{os.getcwd()}/{config.result_path}'
file = f"exp{config.exp_id}_uc{config.use_case}_{config.dim_value}_{config.replicas}_totallag.csv" file = f"exp{config.exp_id}_uc{config.use_case}_{config.dim_value}_{config.replicas}_totallag.csv"
try: try:
trend_slope = trend_slope_computer.compute(cwd, file, WARMUP_SEC, THRESHOLD) trend_slope = trend_slope_computer.compute(cwd, file, WARMUP_SEC)
except Exception as e: except Exception as e:
err_msg = 'Computing trend slope failed' err_msg = 'Computing trend slope failed'
print(err_msg) print(err_msg)
logging.exception(err_msg) logging.exception(err_msg)
print('Mark this subexperiment as not successful and continue benchmark') print('Mark this subexperiment as not successful and continue benchmark')
return 0 return False
print(f"Trend Slope: {trend_slope}") print(f"Trend Slope: {trend_slope}")
success = 0 if trend_slope > THRESHOLD else 1
return success return trend_slope < threshold
...@@ -31,8 +31,8 @@ def load_variables(): ...@@ -31,8 +31,8 @@ def load_variables():
def main(uc, loads, instances_list, partitions, cpu_limit, memory_limit, def main(uc, loads, instances_list, partitions, cpu_limit, memory_limit,
duration, domain_restriction, search_strategy, prometheus_base_url, duration, domain_restriction, search_strategy, threshold,
reset, namespace, result_path, configurations): prometheus_base_url, reset, namespace, result_path, configurations):
print( print(
f"Domain restriction of search space activated: {domain_restriction}") f"Domain restriction of search space activated: {domain_restriction}")
...@@ -107,6 +107,7 @@ def main(uc, loads, instances_list, partitions, cpu_limit, memory_limit, ...@@ -107,6 +107,7 @@ def main(uc, loads, instances_list, partitions, cpu_limit, memory_limit,
result_path=result_path, result_path=result_path,
domain_restriction_strategy=domain_restriction_strategy, domain_restriction_strategy=domain_restriction_strategy,
search_strategy=search_strategy_method, search_strategy=search_strategy_method,
threshold=threshold,
subexperiment_executor=subexperiment_executor, subexperiment_executor=subexperiment_executor,
subexperiment_evaluator=subexperiment_evaluator) subexperiment_evaluator=subexperiment_evaluator)
...@@ -119,10 +120,11 @@ if __name__ == '__main__': ...@@ -119,10 +120,11 @@ if __name__ == '__main__':
args = load_variables() args = load_variables()
if args.reset_only: if args.reset_only:
print('Only reset the cluster') print('Only reset the cluster')
run_uc.main(None, None, None, None, None, None, None, None, run_uc.main(None, None, None, None, None, None, None, None, None,
None, None, args.namespace, None, None, reset_only=True) None, args.namespace, None, None, reset_only=True)
else: else:
main(args.uc, args.loads, args.instances_list, args.partitions, main(args.uc, args.loads, args.instances_list, args.partitions,
args.cpu_limit, args.memory_limit, args.duration, args.cpu_limit, args.memory_limit, args.duration,
args.domain_restriction, args.search_strategy, args.prometheus, args.domain_restriction, args.search_strategy,
args.reset, args.namespace, args.path, args.configurations) args.threshold, args.prometheus, args.reset, args.namespace,
args.path, args.configurations)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment