Summary plots
This commit is contained in:
parent
f450c68039
commit
09764b6107
3 changed files with 550 additions and 70 deletions
10
README.md
10
README.md
|
|
@ -135,15 +135,11 @@ sudo chmod u+s powercap
|
|||
### Grid5000
|
||||
|
||||
```bash
|
||||
ssh lyon.g5k
|
||||
oarsub -q default -l host=2,walltime=2 -p "wattmeter=YES" -I
|
||||
oarsub -q default -l host=2,walltime=2 -p "nova" -I
|
||||
ssh rennes.g5k
|
||||
oarsub -q default -l host=2,walltime=2 -p "paradoxe AND wattmeter=YES" -I
|
||||
# Check the name of the other node in https://intranet.grid5000.fr/oar/Lyon/drawgantt-svg/
|
||||
# Let's call them p1 and p2
|
||||
ping p2
|
||||
# Note p2 addr to exp.py
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
pip3 install fabric
|
||||
pip3 install fabric pyOpenSSL
|
||||
python exp.py make g5k -c
|
||||
python exp.py send g5k
|
||||
|
||||
|
|
|
|||
92
exp.py
92
exp.py
|
|
@ -73,13 +73,13 @@ CONFIGS = {
|
|||
"pi3": {
|
||||
"experiments": [
|
||||
#"impl-cipher-ver",
|
||||
"impl-cert-ver",
|
||||
#"impl-cert-ver",
|
||||
#"impl-kex-ver",
|
||||
#"zrtt",
|
||||
#"realistic"
|
||||
"realistic"
|
||||
],
|
||||
"sides": [
|
||||
#"client",
|
||||
"client",
|
||||
"server",
|
||||
],
|
||||
"tls": [
|
||||
|
|
@ -87,9 +87,9 @@ CONFIGS = {
|
|||
True,
|
||||
],
|
||||
"records": [
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300 },
|
||||
#{ "filename": "yt2-ads", "repeat": 10000, "time": 600 },
|
||||
#{ "filename": "yt2-ublock", "repeat": 10000, "time": 600 },
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
{ "filename": "yt2-ads", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
{ "filename": "yt2-ublock", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
#{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 100 },
|
||||
],
|
||||
"repo_dir": "/home/tuxmain/reps/tlsbench",
|
||||
|
|
@ -108,29 +108,32 @@ CONFIGS = {
|
|||
"idle": "idle - - - - - - - - - - - 600.000081539154 0.0 896 4792 0.5399999999999991 0 -",
|
||||
"notify_listen": ("0.0.0.0", 8090),
|
||||
"notify_addr": "192.168.3.1:8090",
|
||||
"concurrency": "4",
|
||||
"concurrency": "1",
|
||||
},
|
||||
# i7-4790 -> core2
|
||||
"core2": {
|
||||
"experiments": [
|
||||
"impl-cipher-ver",
|
||||
"impl-cert-ver",
|
||||
"impl-kex-ver",
|
||||
#"impl-cipher-ver",
|
||||
#"impl-cert-ver",
|
||||
#"impl-kex-ver",
|
||||
#"zrtt",
|
||||
#"realistic",
|
||||
"realistic",
|
||||
#"debug",
|
||||
],
|
||||
"sides": [
|
||||
"client",
|
||||
#"server",
|
||||
"server",
|
||||
],
|
||||
"tls": [
|
||||
#False,
|
||||
True,
|
||||
False,
|
||||
#True,
|
||||
],
|
||||
"records": [
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300 },
|
||||
#{ "filename": "yt2-ads", "repeat": 10000, "time": 600 },
|
||||
#{ "filename": "yt2-ublock", "repeat": 10000, "time": 600 },
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 3 },
|
||||
{ "filename": "yt2-ads", "repeat": 10000, "time": 300, "reproduce": 3 },
|
||||
{ "filename": "yt2-ublock", "repeat": 10000, "time": 300, "reproduce": 3 },
|
||||
#{ "filename": "test", "repeat": 1, "time": 10 },
|
||||
#{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 100 },
|
||||
],
|
||||
"repo_dir": "/home/tuxmain/reps/tlsbench",
|
||||
"exp_dir": "/dev/shm/exp",
|
||||
|
|
@ -148,6 +151,7 @@ CONFIGS = {
|
|||
"idle": "idle - - - - - - - - - 1777360401.7482355 1777361601.7482355 1200.0000903606415 0 589 4764 3.478999999999999 0 -",
|
||||
"notify_listen": ("0.0.0.0", 8090),
|
||||
"notify_addr": "192.168.3.1:8090",
|
||||
"concurrency": "1",
|
||||
},
|
||||
"core2-local": {
|
||||
"experiments": [
|
||||
|
|
@ -182,11 +186,11 @@ CONFIGS = {
|
|||
# i7-4790 -> i5-7300HQ
|
||||
"i5": {
|
||||
"experiments": [
|
||||
"impl-cipher-ver",
|
||||
"impl-cert-ver",
|
||||
#"impl-cipher-ver",
|
||||
#"impl-cert-ver",
|
||||
#"impl-kex-ver",
|
||||
#"zrtt",
|
||||
#"realistic",
|
||||
"realistic",
|
||||
],
|
||||
"sides": [
|
||||
"client",
|
||||
|
|
@ -197,9 +201,9 @@ CONFIGS = {
|
|||
True,
|
||||
],
|
||||
"records": [
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300 },
|
||||
#{ "filename": "yt2-ads", "repeat": 10000, "time": 600 },
|
||||
#{ "filename": "yt2-ublock", "repeat": 10000, "time": 600 },
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
{ "filename": "yt2-ads", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
{ "filename": "yt2-ublock", "repeat": 10000, "time": 300, "reproduce": 2 },
|
||||
#{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 100 },
|
||||
],
|
||||
"repo_dir": "/home/tuxmain/reps/tlsbench",
|
||||
|
|
@ -220,7 +224,8 @@ CONFIGS = {
|
|||
"notify_addr": "192.168.3.1:8090",
|
||||
"ld_preload": {
|
||||
"openssl": "/home/tuxmain/reps/tlsbench/libssl.so:/home/tuxmain/reps/tlsbench/libcrypto.so",
|
||||
}
|
||||
},
|
||||
"concurrency": "1",
|
||||
},
|
||||
"i5-local": {
|
||||
"experiments": [
|
||||
|
|
@ -265,23 +270,23 @@ CONFIGS = {
|
|||
"server",
|
||||
],
|
||||
"tls": [
|
||||
False,
|
||||
#False,
|
||||
True,
|
||||
],
|
||||
"records": [
|
||||
# Can't repeat more than 8000 times here
|
||||
# TODO check if netreplay client frees ports correctly, or try to reuse ports
|
||||
{ "filename": "wp2", "repeat": 8000, "time": 180 },
|
||||
{ "filename": "yt2-ads", "repeat": 8000, "time": 180 },
|
||||
{ "filename": "yt2-ublock", "repeat": 8000, "time": 180 },
|
||||
#{ "filename": "wp2", "repeat": 10000, "time": 300, "reproduce": 100 },
|
||||
#{ "filename": "wp2", "repeat": 8000, "time": 180 },
|
||||
#{ "filename": "yt2-ads", "repeat": 8000, "time": 180 },
|
||||
#{ "filename": "yt2-ublock", "repeat": 8000, "time": 180 },
|
||||
{ "filename": "wp2", "repeat": 10000, "time": 120, "reproduce": 10 },
|
||||
],
|
||||
"repo_dir": "/home/pengelib/tlsbench",
|
||||
"exp_dir": "/dev/shm/exp",
|
||||
"log_backup_dir": "/home/pengelib",
|
||||
"local_addr": "TODO",
|
||||
"remote_addr": "172.16.52.6",
|
||||
"remote_ssh": "pengelib@gros-69",
|
||||
"local_addr": "172.16.101.x",
|
||||
"remote_addr": "172.16.101.x",
|
||||
"remote_ssh": "pengelib@paradoxe-x",
|
||||
"remote_psw": None,
|
||||
"remote_repo_dir": "/home/pengelib/tlsbench",
|
||||
"wattmeter": False,
|
||||
|
|
@ -289,9 +294,9 @@ CONFIGS = {
|
|||
"rapl": False,
|
||||
"sa": False,
|
||||
"listen_port": 8080,
|
||||
"idle": "idle - - - - - - - - - 1775721200 1775721800 600 0 222346 1105446 10.105035525271305 0 -",
|
||||
"idle": "idle - - - - - - - - - 1779276600 1779277200 600 0 222346 1105446 2.935994312264558 0 -",
|
||||
"notify_listen": ("0.0.0.0", 8090),
|
||||
"notify_addr": "TODO:8090",
|
||||
"notify_addr": "172.16.101.x:8090",
|
||||
"ld_preload": {
|
||||
"openssl": "/home/pengelib/openssl-openssl-3.6.1/libssl.so.3:/home/pengelib/openssl-openssl-3.6.1/libcrypto.so.3",
|
||||
}
|
||||
|
|
@ -351,13 +356,13 @@ CERT_SIGN_ALGS = [
|
|||
"rsa2048", "rsa3072", "rsa4096", # widely used
|
||||
]
|
||||
IMPLS = [
|
||||
#"aws-lc", # Amazon's crypto widely used in Rust stuff
|
||||
"aws-lc", # Amazon's crypto widely used in Rust stuff
|
||||
#"boring", # Google's fork of OpenSSL used in Chrome and Android
|
||||
#"graviola", # New crypto in Rust
|
||||
#"openssl", # widely used
|
||||
#"openssl-static",
|
||||
#"ring", # used in most Rust stuff
|
||||
"symcrypt", # Microsoft's crypto
|
||||
#"symcrypt", # Microsoft's crypto
|
||||
]
|
||||
# Symmetric ciphers
|
||||
# They also allow to choose the TLS version.
|
||||
|
|
@ -449,12 +454,11 @@ EXPERIMENTS = {
|
|||
"debug": {
|
||||
"impls": IMPLS,
|
||||
"ciphers": [
|
||||
"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
#"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
"AES_256_GCM_SHA384",
|
||||
],
|
||||
"kexes": ["X25519"],
|
||||
"kexes": ["X25519MLKEM768"],
|
||||
"cert": ["prime256v1"],
|
||||
"earlydata": ["0"],
|
||||
"earlydata": ["1"],
|
||||
},
|
||||
"realistic": {
|
||||
"impls": IMPLS,
|
||||
|
|
@ -463,14 +467,14 @@ EXPERIMENTS = {
|
|||
"AES_256_GCM_SHA384",
|
||||
#"CHACHA20_POLY1305_SHA256",
|
||||
#"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
#"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
#"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
||||
],
|
||||
"kexes": [
|
||||
"X25519",
|
||||
#"SECP256R1",
|
||||
#"SECP384R1",
|
||||
#"X25519MLKEM768",
|
||||
"X25519MLKEM768",
|
||||
#"SECP256R1MLKEM768",
|
||||
#"MLKEM768",
|
||||
],
|
||||
|
|
@ -482,7 +486,7 @@ EXPERIMENTS = {
|
|||
#"rsa4096",
|
||||
"realistic",
|
||||
],
|
||||
"earlydata": ["1"],
|
||||
"earlydata": ["0", "1"],
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -845,7 +849,7 @@ def run_exp(config, only_record=None, idle=False, shutdown=False, debug=False):
|
|||
for kex in exp["kexes"]:
|
||||
for cipher in exp["ciphers"]:
|
||||
for earlydata in exp["earlydata"]:
|
||||
if not alg_filter(kex, alg, cipher, impl):
|
||||
if not alg_filter(kex, alg, cipher, impl) or (earlydata == "1" and "WITH" in cipher):
|
||||
continue
|
||||
for tls in config["tls"]:
|
||||
tls_int = int(tls)
|
||||
|
|
|
|||
518
plots.py
518
plots.py
|
|
@ -66,6 +66,18 @@ CRITERION_TITLE = {
|
|||
"kex": "key exchange",
|
||||
"ed": "0-RTT",
|
||||
}
|
||||
PRETTY_TABLE = {
|
||||
"pi3": "$\\pi$3",
|
||||
"wp2": "WP",
|
||||
"yt2-ads": "YT",
|
||||
"yt2-ublock": "YT+µ",
|
||||
}
|
||||
PRETTY_TABLE_GNUPLOT = {
|
||||
"pi3": "$\\\\pi$3",
|
||||
"wp2": "WP",
|
||||
"yt2-ads": "YT",
|
||||
"yt2-ublock": "YT+µ",
|
||||
}
|
||||
|
||||
def impl_title(impl):
|
||||
# Gnuplot does not escape underscores when generating tex
|
||||
|
|
@ -79,6 +91,13 @@ PLOTS_DIR = "/dev/shm/plots"
|
|||
#WS_PER_BYTE = 0.06 * 1000 * 3600 / 1024**3
|
||||
WS_PER_BYTE = 0.001875 * 1000 * 3600 / 1024**3
|
||||
|
||||
# Round and ensure exactly n decimal digits
|
||||
def roundz(x, n):
|
||||
s = str(round(x, n))
|
||||
if "." not in s:
|
||||
s += "."
|
||||
return s + "0" * (n - len(s) + s.index(".") + 1)
|
||||
|
||||
def gnuplot_histogram(**kwargs):
|
||||
if "machine" in kwargs and kwargs["machine"] != None:
|
||||
kwargs["machine"] = ", " + kwargs["machine"]
|
||||
|
|
@ -638,7 +657,7 @@ def tabulate(lines, separator=" ", endline="", ruler=True):
|
|||
ruler_state = False
|
||||
for line in lines:
|
||||
for col in range(len(line)):
|
||||
if col > 0:
|
||||
if col > 0 and line[col] != None:
|
||||
table += separator
|
||||
table += line[col]
|
||||
rem = widths[col] - len(line[col])
|
||||
|
|
@ -775,6 +794,7 @@ def analyze_logs(logs):
|
|||
})
|
||||
return lines
|
||||
|
||||
# Group items by equality classes on the tuple of "unique" values, and filter by constraints
|
||||
def aggregate(items, unique, constraints=[]):
|
||||
results = {}
|
||||
for item in items:
|
||||
|
|
@ -792,6 +812,7 @@ def aggregate(items, unique, constraints=[]):
|
|||
continue
|
||||
|
||||
unique_key = tuple(item[u] for u in unique)
|
||||
print(unique_key)
|
||||
if unique_key not in results:
|
||||
results[unique_key] = {u: item[u] for u in unique}
|
||||
results[unique_key]["items"] = [item]
|
||||
|
|
@ -800,6 +821,104 @@ def aggregate(items, unique, constraints=[]):
|
|||
|
||||
return results
|
||||
|
||||
# Average to_average values of equality classes on the tuple of "unique" values
|
||||
def average_logs(items, unique, to_average):
|
||||
results = []
|
||||
aggregated = aggregate(items, unique)
|
||||
for key in aggregated:
|
||||
avg = aggregated[key]["items"][0]
|
||||
for item in aggregated[key]["items"][1:]:
|
||||
for k in to_average:
|
||||
avg[k] += item[k]
|
||||
for k in to_average:
|
||||
avg[k] /= len(aggregated[key]["items"])
|
||||
results.append(avg)
|
||||
return results
|
||||
|
||||
# Average to_average values of equality classes on the tuple of "unique" values
|
||||
def average_items(items, to_average, target=None):
|
||||
avg = items[0]
|
||||
for item in items[1:]:
|
||||
for k in to_average:
|
||||
avg[k] += item[k]
|
||||
for k in to_average:
|
||||
avg[k] /= len(items)
|
||||
if len(items) < 3:
|
||||
print("Only", len(items), "for", target, avg)
|
||||
return avg
|
||||
|
||||
def analyze_average_logs(logs, target=None):
|
||||
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"))
|
||||
if plain_result_key(log) not in plain_results:
|
||||
plain_results[plain_result_key(log)] = []
|
||||
plain_results[plain_result_key(log)].append({
|
||||
"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"))
|
||||
if result_key(log) not in results:
|
||||
results[result_key(log)] = []
|
||||
results[result_key(log)].append({
|
||||
"exp": log["exp"],
|
||||
"side": log["side"],
|
||||
"record": log["record"],
|
||||
"impl": log["impl"],
|
||||
"alg": log["alg"],
|
||||
"kex": log["kex"],
|
||||
"cipher": log["cipher"],
|
||||
"ed": log["ed"],
|
||||
"idle": idle_val["energy"],
|
||||
"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,
|
||||
})
|
||||
|
||||
for key in plain_results:
|
||||
plain_results[key] = average_items(plain_results[key], ["cpu", "total_energy", "energy", "in", "out"], target=target)
|
||||
for key in results:
|
||||
results[key] = average_items(results[key], ["cpu", "total_energy", "energy", "in", "out"], target=target)
|
||||
|
||||
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"],
|
||||
"idle": r["idle"],
|
||||
"tls": r,
|
||||
"plain": p,
|
||||
})
|
||||
return lines
|
||||
|
||||
def fzfill(x, n):
|
||||
if type(x) != str:
|
||||
x = str(round(x, n))
|
||||
|
|
@ -898,6 +1017,335 @@ def make_tx_summary(client_logs, server_logs):
|
|||
])
|
||||
print(tabulate(latex, separator=" & ", endline="\\\\ \\cline{2-8}", ruler=False))
|
||||
|
||||
def make_tx_plot(logs_by_target, server_target):
|
||||
txs = []
|
||||
lines = [["exp", "record", "alg", "kex", "cipher", "ed", "client_target", "server_target", "client_impl", "server_impl", "plain (J/S)", "TLS (J/S)", "TLS only (J/S)", "TLS io (J/S)", "TLS rel"]]
|
||||
server_logs = logs_by_target[server_target]
|
||||
server_results = analyze_logs(server_logs)
|
||||
for client_target in logs_by_target:
|
||||
client_logs = logs_by_target[client_target]
|
||||
client_results = analyze_logs(client_logs)
|
||||
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
|
||||
tls_only_io_energy = tls_io_avg * WS_PER_BYTE - plain_io_avg * WS_PER_BYTE
|
||||
txs.append({
|
||||
"client_target": client_target,
|
||||
"server_target": server_target,
|
||||
"exp": client["exp"],
|
||||
"record": client["record"],
|
||||
"alg": client["alg"],
|
||||
"kex": client["kex"],
|
||||
"cipher": client["cipher"],
|
||||
"ed": client["ed"],
|
||||
"version": VER_LABEL[client["cipher"]],
|
||||
"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,
|
||||
"tls_only_io_energy": tls_only_io_energy,
|
||||
})
|
||||
lines.append([
|
||||
client["exp"],
|
||||
client["record"],
|
||||
client["alg"],
|
||||
client["kex"],
|
||||
client["cipher"],
|
||||
client["ed"],
|
||||
client_target,
|
||||
server_target,
|
||||
client["impl"],
|
||||
server["impl"],
|
||||
str(round(plain_energy, 2)),
|
||||
str(round(tls_energy, 2)),
|
||||
str(round(tls_only_energy, 2)),
|
||||
str(round(tls_only_io_energy, 2)),
|
||||
str(round(tls_rel_energy*100, 2))+"%",
|
||||
])
|
||||
print(tabulate(lines))
|
||||
|
||||
aggregated = aggregate(txs, ["exp", "record", "alg"], {})
|
||||
latex = []
|
||||
for cluster_k in aggregated:
|
||||
cluster = aggregated[cluster_k]
|
||||
items_to_find = {"kex": ["X25519", "X25519MLKEM768"], "cipher": []}
|
||||
items_to_find = {
|
||||
"1.2": {"kex": "X25519", "cipher": "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384"},
|
||||
"ec": {"kex": "X25519", "cipher": "AES_256_GCM_SHA384", "ed": "0"},
|
||||
"pq": {"kex": "X25519MLKEM768", "ed": "0"},
|
||||
"ec+ed": {"kex": "X25519", "cipher": "AES_256_GCM_SHA384", "ed": "1"},
|
||||
"pq+ed": {"kex": "X25519MLKEM768", "ed": "1"},
|
||||
}
|
||||
items = {}
|
||||
for k in items_to_find:
|
||||
for item in cluster["items"]:
|
||||
ok = True
|
||||
for kk in items_to_find[k]:
|
||||
if item[kk] != items_to_find[k][kk]:
|
||||
ok = False
|
||||
break
|
||||
# named breaks please!
|
||||
if ok:
|
||||
items[k] = item
|
||||
latex.append([
|
||||
server_target,
|
||||
client_target,
|
||||
cluster["record"],
|
||||
"$"+str(round(items["ec"]["plain_energy"], 2))+"$",
|
||||
("$" + str(fzfill(items["1.2"]["tls_only_energy"], 2)) + "$ ($" + str(fzfill(items["1.2"]["tls_rel_energy"]*100, 2)) + "\\%$)") if "1.2" in items else "",
|
||||
"$" + str(fzfill(items["ec"]["tls_only_energy"], 2)) + "$ ($" + str(fzfill(items["ec"]["tls_rel_energy"]*100, 2)) + "\\%$)",
|
||||
("$" + str(fzfill(items["pq"]["tls_only_energy"], 2)) + "$ ($" + str(fzfill(items["pq"]["tls_rel_energy"]*100, 2)) + "\\%$)") if "pq" in items else "",
|
||||
("$" + str(fzfill(items["ec+ed"]["tls_only_energy"], 2)) + "$ ($" + str(fzfill(items["ec+ed"]["tls_rel_energy"]*100, 2)) + "\\%$)") if "ec+ed" in items else "",
|
||||
("$" + str(fzfill(items["pq+ed"]["tls_only_energy"], 2)) + "$ ($" + str(fzfill(items["pq+ed"]["tls_rel_energy"]*100, 2)) + "\\%$)") if "pq+ed" in items else "",
|
||||
])
|
||||
print(tabulate(latex, separator=" & ", endline="\\\\ \\cline{3-9}", ruler=False))
|
||||
|
||||
def make_summary_plot(logs_by_target):
|
||||
lines = [["exp", "record", "alg", "kex", "cipher", "ed", "side", "target", "impl", "plain E (J/S)", "TLS E (J/S)", "TLS only E (J/S)", "plain io (o/S)", "TLS io (o/S)", "TLS only io (o/S)", "TLS E rel", "TLS io rel"]]
|
||||
results = []
|
||||
for target in logs_by_target:
|
||||
logs = logs_by_target[target]
|
||||
target_results = analyze_average_logs(logs, target=target)
|
||||
for log in target_results:
|
||||
plain_energy = log["plain"]["energy"]
|
||||
tls_energy = log["tls"]["energy"]
|
||||
tls_only_energy = tls_energy - plain_energy
|
||||
tls_rel_energy = tls_only_energy / plain_energy
|
||||
plain_io = log["plain"]["in"] + log["plain"]["out"]
|
||||
tls_io = log["tls"]["in"] + log["tls"]["out"]
|
||||
tls_only_io = tls_io - plain_io
|
||||
tls_rel_io = tls_only_io / plain_io
|
||||
results.append({
|
||||
"target": target,
|
||||
"exp": log["exp"],
|
||||
"record": log["record"],
|
||||
"alg": log["alg"],
|
||||
"kex": log["kex"],
|
||||
"cipher": log["cipher"],
|
||||
"ed": log["ed"],
|
||||
"version": VER_LABEL[log["cipher"]],
|
||||
"impl": log["impl"],
|
||||
"side": log["side"],
|
||||
"tls": log["tls"],
|
||||
"idle_energy": log["idle"],
|
||||
"plain_energy": plain_energy,
|
||||
"tls_energy": tls_energy,
|
||||
"tls_only_energy": tls_only_energy,
|
||||
"plain_io": plain_io,
|
||||
"tls_io": tls_io,
|
||||
"tls_only_io": tls_only_io,
|
||||
"tls_rel_energy": tls_rel_energy,
|
||||
"tls_rel_io": tls_rel_io,
|
||||
})
|
||||
lines.append([
|
||||
log["exp"],
|
||||
log["record"],
|
||||
log["alg"],
|
||||
log["kex"],
|
||||
log["cipher"],
|
||||
log["ed"],
|
||||
log["side"],
|
||||
target,
|
||||
log["impl"],
|
||||
str(round(plain_energy, 2)),
|
||||
str(round(tls_energy, 2)),
|
||||
str(round(tls_only_energy, 2)),
|
||||
str(round(plain_io, 2)),
|
||||
str(round(tls_io, 2)),
|
||||
str(round(tls_only_io, 2)),
|
||||
str(round(tls_rel_energy*100, 2))+"%",
|
||||
str(round(tls_rel_io*100, 2))+"%",
|
||||
])
|
||||
print(tabulate(lines))
|
||||
print()
|
||||
|
||||
|
||||
print("\
|
||||
\\multicolumn{1}{|c|}{\\textbf{Target}}&\
|
||||
\\multicolumn{1}{|c|}{\\textbf{Idle}}&\
|
||||
\\multicolumn{1}{|c|}{\\textbf{Record}}&\
|
||||
\\multicolumn{1}{|c|}{\\textbf{Side}}&\
|
||||
\\multicolumn{1}{|c|}{\\textbf{Energy}}&\
|
||||
\\multicolumn{2}{|c|}{\\textbf{Traffic}}\
|
||||
\\\\")
|
||||
latex_lines = {}
|
||||
latex_keys = []
|
||||
for log in results:
|
||||
key = (log["target"], log["record"], log["side"])
|
||||
if key in latex_lines:
|
||||
continue
|
||||
latex_keys.append(key)
|
||||
latex_lines[key] = [
|
||||
PRETTY_TABLE.get(log["target"], log["target"]),
|
||||
"${}$W".format(roundz(log["idle_energy"], 2)),
|
||||
PRETTY_TABLE[log["record"]],
|
||||
log["side"],
|
||||
"${}$J".format(roundz(log["plain_energy"], 2)),
|
||||
"${}$MB".format(roundz(log["plain_io"]/1024**2, 1)),
|
||||
#"${}$J".format(roundz(log["plain_io"] * WS_PER_BYTE, 2))
|
||||
"${}$J".format(int(log["plain_io"] * WS_PER_BYTE))
|
||||
]
|
||||
latex_keys.sort()
|
||||
last = None
|
||||
multirows = [1, 1, 1]
|
||||
key_i = 0
|
||||
for key in latex_keys:
|
||||
line = latex_lines[key].copy()
|
||||
|
||||
for i in range(len(multirows)):
|
||||
multirows[i] -= 1
|
||||
if multirows[i] > 0:
|
||||
line[i] = ""
|
||||
else:
|
||||
multirows[i] = 1
|
||||
for nkey in latex_keys[key_i+1:]:
|
||||
nline = latex_lines[nkey]
|
||||
if nline[i] == line[i]:
|
||||
multirows[i] += 1
|
||||
else:
|
||||
break
|
||||
if multirows[i] > 1:
|
||||
line[i] = "\\multirow{{{}}}*{{{}}}".format(multirows[i], line[i])
|
||||
|
||||
cline = 1
|
||||
if last != None:
|
||||
if last[0] == latex_lines[key][0]:
|
||||
cline = 3
|
||||
if last[2] == latex_lines[key][2]:
|
||||
cline = 4
|
||||
if last[3] == latex_lines[key][3]:
|
||||
cline = 5
|
||||
|
||||
print(f"\cline{{{cline}-7}} " + " & ".join(line) + "\\\\")
|
||||
last = latex_lines[key]
|
||||
key_i += 1
|
||||
|
||||
f = open("/dev/shm/plots/summary.dat", "w")
|
||||
f.write("Variant Order Client Server Traffic\n")
|
||||
for log in results:
|
||||
variant = None
|
||||
if "WITH" in log["cipher"]:
|
||||
variant = "1.2-x25519 0"
|
||||
elif log["ed"] == "1":
|
||||
if "MLKEM" in log["kex"]:
|
||||
variant = "1.3-x25519mlkem768-0RTT 4"
|
||||
else:
|
||||
variant = "1.3-x25519-0RTT 3"
|
||||
else:
|
||||
if "MLKEM" in log["kex"]:
|
||||
variant = "1.3-x25519mlkem768 2"
|
||||
else:
|
||||
variant = "1.3-x25519 1"
|
||||
if variant == None:
|
||||
print("Error: unknown variant", log)
|
||||
exit(1)
|
||||
f.write(" ".join([
|
||||
variant,
|
||||
str(log["tls_rel_energy"]) if (log["side"] == "client") else "-",
|
||||
str(log["tls_rel_energy"]) if (log["side"] == "server") else "-",
|
||||
str(log["tls_rel_io"]),
|
||||
]) + "\n")
|
||||
f.close()
|
||||
|
||||
cmps = {
|
||||
"pq-ec": {
|
||||
"new": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519MLKEM768", "ed": "0"},
|
||||
"old": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519", "ed": "0"},
|
||||
},
|
||||
"ec0rtt-ec": {
|
||||
"new": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519", "ed": "1"},
|
||||
"old": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519", "ed": "0"},
|
||||
},
|
||||
"pq0rtt-pq": {
|
||||
"new": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519MLKEM768", "ed": "1"},
|
||||
"old": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519MLKEM768", "ed": "0"},
|
||||
},
|
||||
"pq0rtt-ec": {
|
||||
"new": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519MLKEM768", "ed": "1"},
|
||||
"old": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519", "ed": "0"},
|
||||
},
|
||||
"13-12": {
|
||||
"new": {"cipher": "AES_256_GCM_SHA384", "kex": "X25519", "ed": "0"},
|
||||
"old": {"cipher": "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384", "kex": "X25519", "ed": "0"},
|
||||
},
|
||||
}
|
||||
|
||||
for cmp_name in cmps:
|
||||
cmp = cmps[cmp_name]
|
||||
samples_energy_client = []
|
||||
samples_energy_server = []
|
||||
samples_io = []
|
||||
for log_new in results:
|
||||
ok = True
|
||||
for filter in cmp["new"]:
|
||||
if log_new[filter] != cmp["new"][filter]:
|
||||
ok = False
|
||||
break
|
||||
if not ok:
|
||||
continue
|
||||
key_new = (log_new["exp"], log_new["target"], log_new["impl"], log_new["record"], log_new["side"])
|
||||
for log_old in results:
|
||||
ok = True
|
||||
for filter in cmp["old"]:
|
||||
if log_old[filter] != cmp["old"][filter]:
|
||||
ok = False
|
||||
break
|
||||
if not ok:
|
||||
continue
|
||||
key_old = (log_old["exp"], log_old["target"], log_old["impl"], log_old["record"], log_old["side"])
|
||||
if key_new == key_old:
|
||||
if log_new["side"] == "server":
|
||||
samples_energy_server.append((log_new["tls_energy"] / log_old["tls_energy"] - 1.0) * 100.0)
|
||||
else:
|
||||
samples_energy_client.append((log_new["tls_energy"] / log_old["tls_energy"] - 1.0) * 100.0)
|
||||
samples_io.append((log_new["tls_io"] / log_old["tls_io"] - 1.0) * 100.0)
|
||||
break
|
||||
samples_energy_client.sort(reverse=True)
|
||||
samples_energy_server.sort(reverse=True)
|
||||
f = open(f"/dev/shm/plots/{cmp_name}-client.dat", "w")
|
||||
for sample in samples_energy_client:
|
||||
f.write(f"{sample}\n")
|
||||
f.close()
|
||||
f = open(f"/dev/shm/plots/{cmp_name}-server.dat", "w")
|
||||
for sample in samples_energy_server:
|
||||
f.write(f"{sample}\n")
|
||||
f.close()
|
||||
f = open(f"/dev/shm/plots/{cmp_name}-io.dat", "w")
|
||||
for sample in samples_io:
|
||||
f.write(f"{sample}\n")
|
||||
f.close()
|
||||
|
||||
f_energy = open("/dev/shm/plots/energy-global.dat", "w")
|
||||
f_io = open("/dev/shm/plots/io-global.dat", "w")
|
||||
for log in results:
|
||||
if log["target"] == "pi3" and "yt" in log["record"]:
|
||||
continue
|
||||
f_energy.write("{}-{} {}\n".format(PRETTY_TABLE_GNUPLOT.get(log["target"], log["target"]), log["side"], log["tls_rel_energy"] * 100.0))
|
||||
f_io.write("{}-{} {}\n".format(PRETTY_TABLE_GNUPLOT.get(log["target"], log["target"]), log["side"], log["tls_rel_io"] * 100.0))
|
||||
f_energy.close()
|
||||
f_io.close()
|
||||
|
||||
def compute_box_plot(a):
|
||||
a.sort()
|
||||
median = a[len(a)//2] if len(a)%2 == 1 else (a[len(a)//2-1]+a[len(a)//2])/2
|
||||
|
|
@ -920,6 +1368,37 @@ def make_stability_plot(logs_by_target):
|
|||
"io": float(log["bytes_in"])+float(log["bytes_out"]) / float(log["time"]),
|
||||
}
|
||||
|
||||
all_results = {}
|
||||
for target in logs_by_target:
|
||||
logs = logs_by_target[target]
|
||||
for log in logs:
|
||||
if log["exp"] == "idle":
|
||||
continue
|
||||
n = float(log.get("n", "1000"))
|
||||
key = "{}-{}".format(target, log["side"])
|
||||
if key not in all_results:
|
||||
all_results[key] = []
|
||||
all_results[key].append({
|
||||
"energy": (float(log[COL["energy"]]) * 3600.0 - idle_val[target]["energy"] * float(log["time"])) / n,
|
||||
"io": (float(log["bytes_in"])+float(log["bytes_out"]) - idle_val[target]["io"] * float(log["time"])) / n / 1024**2
|
||||
})
|
||||
|
||||
means = {key: {
|
||||
"energy": sum([i["energy"] for i in all_results[key]])/len(all_results[key]),
|
||||
"io": sum([i["io"] for i in all_results[key]])/len(all_results[key]),
|
||||
} for key in all_results}
|
||||
|
||||
for key in all_results:
|
||||
for result in all_results[key]:
|
||||
f.write("{} {} {} {} {}\n".format(
|
||||
key,
|
||||
result["energy"],
|
||||
result["io"],
|
||||
(result["energy"] / means[key]["energy"] - 1.0) * 100.0,
|
||||
(result["io"] / means[key]["io"] - 1.0) * 100.0,
|
||||
))
|
||||
|
||||
"""
|
||||
for target in logs_by_target:
|
||||
logs = logs_by_target[target]
|
||||
for log in logs:
|
||||
|
|
@ -931,7 +1410,7 @@ def make_stability_plot(logs_by_target):
|
|||
log["side"],
|
||||
(float(log[COL["energy"]]) * 3600.0 - idle_val[target]["energy"] * float(log["time"])) / n,
|
||||
(float(log["bytes_in"])+float(log["bytes_out"]) - idle_val[target]["io"] * float(log["time"])) / n / 1024**2
|
||||
))
|
||||
))"""
|
||||
f.close()
|
||||
|
||||
def getargv(arg:str, default="", n:int=1, args:list=sys.argv):
|
||||
|
|
@ -1015,24 +1494,25 @@ if __name__ == "__main__":
|
|||
make_profile_plot_grouped(logs, "impl-cert-ver", "cert", side, record, "impl", no_flamegraph=no_flamegraph, machine=machine, maketitle=maketitle, version="1.3")
|
||||
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)
|
||||
# Args: stab <file1> <target1> [<file2> <target2>] [...]
|
||||
# First target is the server
|
||||
server = sys.argv[3]
|
||||
logs_by_target = {server: logs}
|
||||
for i in range(4, len(sys.argv), 2):
|
||||
logs_i, records_i = parse_logs(sys.argv[i])
|
||||
target_i = sys.argv[i+1]
|
||||
logs_by_target[target_i] = logs_i
|
||||
make_summary_plot(logs_by_target)
|
||||
elif cmd == "tx":
|
||||
logfile_name = sys.argv[3]
|
||||
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)
|
||||
# Args: stab <file1> <target1> [<file2> <target2>] [...]
|
||||
# First target is the server
|
||||
server = sys.argv[3]
|
||||
logs_by_target = {server: logs}
|
||||
for i in range(4, len(sys.argv), 2):
|
||||
logs_i, records_i = parse_logs(sys.argv[i])
|
||||
target_i = sys.argv[i+1]
|
||||
logs_by_target[target_i] = logs_i
|
||||
make_tx_plot(logs_by_target, server)
|
||||
elif cmd == "correl":
|
||||
from scipy import stats
|
||||
import matplotlib.pyplot as plt
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue