diff --git a/README.md b/README.md index 6a56bb3..4e940eb 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,7 @@ Install dependencies on the target: ```bash sudo apt install acct dtach sudo chmod +s /sbin/sa +pip install pyOpenSSL ``` Modify experiment parameters at the top of `exp.py` to suit your setup and the wanted experiments. @@ -74,6 +75,7 @@ Run: ```bash python exp.py make pi3 -c +python makecerts.py python exp.py send pi3 python exp.py run pi3 --idle ``` diff --git a/exp.py b/exp.py index 803b776..d8609fc 100644 --- a/exp.py +++ b/exp.py @@ -267,7 +267,7 @@ CONFIGS = { "records": [ # Can't repeat more than 8000 times here # TODO check if netreplay client frees ports correctly, or try to reuse ports - { "filename": "wikipedia", "repeat": 8000, "time": 45 }, + { "filename": "wikipedia", "repeat": 8000, "time": 180 }, { "filename": "yt2-ads", "repeat": 8000, "time": 180 }, { "filename": "yt2-ublock", "repeat": 8000, "time": 180 }, ], @@ -284,7 +284,7 @@ CONFIGS = { "rapl": False, "sa": False, "listen_port": 8080, - "idle": "idle - - - - - - - - - 1774429500.8909554 1774430100.9141996 600.0232441425323 0 222346 1105446 8.666666666666666 0 -", + "idle": "idle - - - - - - - - - 1775721200 1775721800 600 0 222346 1105446 10.105035525271305 0 -", "notify_listen": ("0.0.0.0", 8090), "notify_addr": "TODO:8090", "ld_preload": { diff --git a/g5kwatt.py b/g5kwatt.py index 39d58f0..2b0c910 100644 --- a/g5kwatt.py +++ b/g5kwatt.py @@ -4,7 +4,7 @@ def fetch(site, node, start, stop, user, psw): start_str = time.strftime("%Y-%m-%dT%H:%M", time.localtime(int(start))) stop_str = time.strftime("%Y-%m-%dT%H:%M", time.localtime(int(stop+61))) auth = requests.auth.HTTPBasicAuth(user, psw) - url = f"https://api.grid5000.fr/stable/sites/{site}/metrics?nodes={node}&metrics=bmc_node_power_watt&start_time={start_str}&end_time={stop_str}" + url = f"https://api.grid5000.fr/stable/sites/{site}/metrics?nodes={node}&metrics=wattmetre_power_watt&start_time={start_str}&end_time={stop_str}" print(url) resp = requests.get(url, auth=auth) if resp.status_code != 200: @@ -17,7 +17,11 @@ def fetch(site, node, start, stop, user, psw): last_power = None last_time = 0 for sample in data: - t = time.mktime(time.strptime(sample["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z")) + t = None + try: + t = time.mktime(time.strptime(sample["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z")) + except Exception as e: + t = time.mktime(time.strptime(sample["timestamp"], "%Y-%m-%dT%H:%M:%S%z")) if last_power != None: energy += last_power * (t - last_time) last_power = None diff --git a/plots.py b/plots.py index fdd25ff..de9a083 100644 --- a/plots.py +++ b/plots.py @@ -573,6 +573,125 @@ def make_summary(logs): ]) print(tabulate(lines)) +def analyze_logs(logs): + plain_result_key = lambda log: (log["exp"], log["side"], log["record"]) + result_key = lambda log: (log["exp"], log["side"], log["record"], log["impl"], log["alg"], log["kex"], log["cipher"], log["ed"]) + + plain_results = {} + results = {} + idle_val = None + + for log in logs: + if log["exp"] == "idle": + idle_val = { + "cpu": float(log["cpu"]) / float(log["time"]), + "energy": float(log["Wh"]) / float(log["time"]) * 3600, + "in": float(log["bytes_in"]) / float(log["time"]), + "out": float(log["bytes_out"]) / float(log["time"]), + } + if log["tls"] == "0": + n = float(log.get("n", "1000")) + plain_results[plain_result_key(log)] = { + "cpu": (float(log["cpu"]) - idle_val["cpu"] * float(log["time"])) / n, + "total_energy": float(log["Wh"]) * 3600 / n, + "energy": (float(log["Wh"]) * 3600 - idle_val["energy"] * float(log["time"])) / n, + "in": (float(log["bytes_in"]) - idle_val["in"] * float(log["time"])) / n, + "out": (float(log["bytes_out"]) - idle_val["out"] * float(log["time"])) / n, + } + if log["exp"] != "idle" and log["tls"] == "1": + n = float(log.get("n", "1000")) + results[result_key(log)] = { + "exp": log["exp"], + "side": log["side"], + "record": log["record"], + "impl": log["impl"], + "alg": log["alg"], + "kex": log["kex"], + "cipher": log["cipher"], + "ed": log["ed"], + "cpu": (float(log["cpu"]) - idle_val["cpu"] * float(log["time"])) / n, + "total_energy": float(log["Wh"]) * 3600 / n, + "energy": (float(log["Wh"]) * 3600 - idle_val["energy"] * float(log["time"])) / n, + "in": (float(log["bytes_in"]) - idle_val["in"] * float(log["time"])) / n, + "out": (float(log["bytes_out"]) - idle_val["out"] * float(log["time"])) / n, + } + + lines = [] + for k in results: + r = results[k] + p = plain_results[k[:3]] + lines.append({ + "exp": r["exp"], + "side": r["side"], + "record": r["record"], + "impl": r["impl"], + "alg": r["alg"], + "kex": r["kex"], + "cipher": r["cipher"], + "ed": r["ed"], + "tls": r, + "plain": p, + }) + return lines + +def make_tx_summary(client_logs, server_logs): + client_results = analyze_logs(client_logs) + server_results = analyze_logs(server_logs) + txs = [] + lines = [["exp", "record", "alg", "kex", "cipher", "ed", "client", "server", "plain (J/S)", "TLS (J/S)", "TLS only (J/S)", "TLS rel"]] + for client in client_results: + #print("client", client) + if client["side"] != "client": + continue + for server in server_results: + #print("server", server) + if server["side"] != "server": + continue + #print(client, server) + if client["exp"] == server["exp"] \ + and client["record"] == server["record"] \ + and client["alg"] == server["alg"] \ + and client["kex"] == server["kex"] \ + and client["cipher"] == server["cipher"] \ + and client["ed"] == server["ed"]: + plain_io_avg = (client["plain"]["in"] + client["plain"]["out"] + server["plain"]["in"] + server["plain"]["out"]) / 2 + tls_io_avg = (client["tls"]["in"] + client["tls"]["out"] + server["tls"]["in"] + server["tls"]["out"]) / 2 + tls_only_io_avg = tls_io_avg - plain_io_avg + plain_energy = client["plain"]["energy"] + server["plain"]["energy"] + plain_io_avg * WS_PER_BYTE + tls_energy = client["tls"]["energy"] + server["tls"]["energy"] + tls_io_avg * WS_PER_BYTE + tls_only_energy = tls_energy - plain_energy + tls_rel_energy = tls_only_energy / plain_energy + txs.append({ + "exp": client["exp"], + "record": client["record"], + "alg": client["alg"], + "kex": client["kex"], + "cipher": client["cipher"], + "ed": client["ed"], + "client_impl": client["impl"], + "server_impl": server["impl"], + "plain_energy": plain_energy, + "tls_energy": tls_energy, + "tls_only_energy": tls_only_energy, + "tls_rel_energy": tls_rel_energy, + }) + lines.append([ + client["exp"], + client["record"], + client["alg"], + client["kex"], + client["cipher"], + client["ed"], + client["impl"], + server["impl"], + str(round(plain_energy, 2)), + str(round(tls_energy, 2)), + str(round(tls_only_energy, 2)), + str(round(tls_rel_energy*100, 2))+"%", + ]) + + print(tabulate(lines)) + def getargv(arg:str, default="", n:int=1, args:list=sys.argv): if arg in args and len(args) > args.index(arg)+n: return args[args.index(arg)+n] @@ -629,6 +748,23 @@ if __name__ == "__main__": make_profile_plot_grouped(logs, "impl-kex-ver", "kex", side, record, "impl", no_flamegraph=no_flamegraph, machine=machine, maketitle=maketitle, version="1.3") elif cmd == "summary": make_summary(logs) + elif cmd == "tx": + logfile_name = sys.argv[2] + logfile = open(logfile_name, "r") + lines = logfile.readlines() + logfile.close() + colnames = lines[0].removesuffix("\n").split(" ") + logs2 = [] + records = {} + for line in lines[1:]: + cols = line.removesuffix("\n").split(" ") + log = {} + for col in range(len(cols)): + log[colnames[col]] = cols[col] + if log["record"] != "-": + records[log["record"]] = () + logs2.append(log) + make_tx_summary(logs, logs2) elif cmd == "correl": from scipy import stats import matplotlib.pyplot as plt