Point plots
This commit is contained in:
parent
e98eb7380a
commit
0f52f2813d
2 changed files with 170 additions and 13 deletions
|
|
@ -135,8 +135,9 @@ sudo chmod u+s powercap
|
||||||
### Grid5000
|
### Grid5000
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ssh nancy.g5k
|
ssh lyon.g5k
|
||||||
oarsub -q default -l host=2,walltime=2 -p "wattmeter=YES" -I
|
oarsub -q default -l host=2,walltime=2 -p "wattmeter=YES" -I
|
||||||
|
oarsub -q default -l host=2,walltime=2 -p "nova" -I
|
||||||
# Check the name of the other node in https://intranet.grid5000.fr/oar/Lyon/drawgantt-svg/
|
# Check the name of the other node in https://intranet.grid5000.fr/oar/Lyon/drawgantt-svg/
|
||||||
# Let's call them p1 and p2
|
# Let's call them p1 and p2
|
||||||
ping p2
|
ping p2
|
||||||
|
|
|
||||||
180
plots.py
180
plots.py
|
|
@ -74,7 +74,8 @@ PLOTS_DIR = "/dev/shm/plots"
|
||||||
|
|
||||||
# Energy per byte on the network, in W/s
|
# Energy per byte on the network, in W/s
|
||||||
# Estimated at 0.06 kWh/GB by Aslan 2018
|
# Estimated at 0.06 kWh/GB by Aslan 2018
|
||||||
WS_PER_BYTE = 0.06 * 1000 * 3600 / 1024**3
|
#WS_PER_BYTE = 0.06 * 1000 * 3600 / 1024**3
|
||||||
|
WS_PER_BYTE = 0.001875 * 1000 * 3600 / 1024**3
|
||||||
|
|
||||||
def gnuplot_histogram(**kwargs):
|
def gnuplot_histogram(**kwargs):
|
||||||
if "machine" in kwargs and kwargs["machine"] != None:
|
if "machine" in kwargs and kwargs["machine"] != None:
|
||||||
|
|
@ -282,6 +283,70 @@ def make_log_plot(logs, exp, criterion, side, obj, record, machine=None, version
|
||||||
maketitle=maketitle
|
maketitle=maketitle
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def make_log_plot_points(logs_by_target, exp, criterion, side, obj, record):
|
||||||
|
f = open(f"/dev/shm/plots/{obj}_by_{criterion}_{side}_{record}.dat", "w")
|
||||||
|
ciphers = {target: {} for target in logs_by_target}
|
||||||
|
impls = []
|
||||||
|
plain = {target: None for target in logs_by_target}
|
||||||
|
idle_val = {target: None for target in logs_by_target}
|
||||||
|
conv_factor = 1.0
|
||||||
|
if obj == "energy":
|
||||||
|
# Convert Wh to Ws
|
||||||
|
conv_factor = 3600.0
|
||||||
|
|
||||||
|
for target in logs_by_target:
|
||||||
|
logs = logs_by_target[target]
|
||||||
|
for log in logs:
|
||||||
|
if log["exp"] == "idle":
|
||||||
|
idle_val[target] = float(log[COL[obj]]) / float(log["time"]) * conv_factor
|
||||||
|
if log["exp"] != exp or log["record"] != record:
|
||||||
|
continue
|
||||||
|
if log["side"] == side and log["tls"] == "0":
|
||||||
|
n = float(log.get("n", "1000"))
|
||||||
|
plain[target] = (float(log[COL[obj]]) * conv_factor - idle_val[target] * float(log["time"])) / n
|
||||||
|
|
||||||
|
for target in plain:
|
||||||
|
if plain[target] == None:
|
||||||
|
return
|
||||||
|
|
||||||
|
for target in logs_by_target:
|
||||||
|
logs = logs_by_target[target]
|
||||||
|
for log in logs:
|
||||||
|
if log["exp"] == exp and log["record"] == record and log["side"] == side:
|
||||||
|
if version != None and VER_LABEL[log["cipher"]] != version:
|
||||||
|
continue
|
||||||
|
n = float(log.get("n", "1000"))
|
||||||
|
if version == None:
|
||||||
|
ver = VER_LABEL[log["cipher"]]
|
||||||
|
if log[COL[criterion]]+"/"+ver not in ciphers[target]:
|
||||||
|
ciphers[target][log[COL[criterion]]+"/"+ver] = {}
|
||||||
|
ciphers[target][log[COL[criterion]]+"/"+ver][log["impl"]] = (float(log[COL[obj]]) * conv_factor - idle_val[target] * float(log["time"])) / n
|
||||||
|
else:
|
||||||
|
if log[COL[criterion]] not in ciphers[target]:
|
||||||
|
ciphers[target][log[COL[criterion]]] = {}
|
||||||
|
ciphers[target][log[COL[criterion]]][log["impl"]] = (float(log[COL[obj]]) * conv_factor - idle_val[target] * float(log["time"])) / n
|
||||||
|
if log["impl"] not in impls:
|
||||||
|
impls.append(log["impl"])
|
||||||
|
impls.sort()
|
||||||
|
f.write("target {} none {}\n".format(criterion, " ".join([impl_title(impl) for impl in impls])))
|
||||||
|
for target in plain:
|
||||||
|
for cipher in ciphers[target]:
|
||||||
|
for impl in impls:
|
||||||
|
if impl not in ciphers[target][cipher]:
|
||||||
|
ciphers[target][cipher][impl] = 0
|
||||||
|
cipher_parts = cipher.split("/")
|
||||||
|
f.write("{} {}({}) {} {}\n".format(
|
||||||
|
target,
|
||||||
|
ALG_LABEL[cipher_parts[0]],
|
||||||
|
cipher_parts[1],
|
||||||
|
plain[target],
|
||||||
|
" ".join([
|
||||||
|
str(ciphers[target][cipher][impl])
|
||||||
|
for impl in impls
|
||||||
|
]),
|
||||||
|
))
|
||||||
|
f.close()
|
||||||
|
|
||||||
def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, machine=None, version=None, maketitle=False):
|
def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, machine=None, version=None, maketitle=False):
|
||||||
f = open(f"/dev/shm/plots/profile_by_{criterion}_{side}_{record}.dat", "w")
|
f = open(f"/dev/shm/plots/profile_by_{criterion}_{side}_{record}.dat", "w")
|
||||||
runs = []
|
runs = []
|
||||||
|
|
@ -487,26 +552,26 @@ def cmp_versions(logs, exps, criteria, objs):
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def tabulate(lines):
|
def tabulate(lines, separator=" ", endline="", ruler=True):
|
||||||
widths = [0] * len(lines[0])
|
widths = [0] * len(lines[0])
|
||||||
for line in lines:
|
for line in lines:
|
||||||
for col in range(len(line)):
|
for col in range(len(line)):
|
||||||
if len(line[col]) > widths[col]:
|
if len(line[col]) > widths[col]:
|
||||||
widths[col] = len(line[col])
|
widths[col] = len(line[col])
|
||||||
table = ""
|
table = ""
|
||||||
ruler = False
|
ruler_state = False
|
||||||
for line in lines:
|
for line in lines:
|
||||||
for col in range(len(line)):
|
for col in range(len(line)):
|
||||||
if col > 0:
|
if col > 0:
|
||||||
table += " "
|
table += separator
|
||||||
table += line[col]
|
table += line[col]
|
||||||
rem = widths[col] - len(line[col])
|
rem = widths[col] - len(line[col])
|
||||||
if ruler:
|
if ruler_state:
|
||||||
table += " " * (rem % 4) + " · " * (rem // 4)
|
table += " " * (rem % 4) + " · " * (rem // 4)
|
||||||
else:
|
else:
|
||||||
table += " " * rem
|
table += " " * rem
|
||||||
table += "\n"
|
table += endline+"\n"
|
||||||
ruler = not ruler
|
ruler_state ^= ruler
|
||||||
return table
|
return table
|
||||||
|
|
||||||
def make_summary(logs):
|
def make_summary(logs):
|
||||||
|
|
@ -634,6 +699,36 @@ def analyze_logs(logs):
|
||||||
})
|
})
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
def aggregate(items, unique, constraints=[]):
|
||||||
|
results = {}
|
||||||
|
for item in items:
|
||||||
|
satisfied = True
|
||||||
|
for constraint in constraints:
|
||||||
|
if type(constraints[constraint]) == list:
|
||||||
|
if item[constraint] not in constraints[constraint]:
|
||||||
|
satisfied = False
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if item[constraint] != constraints[constraint]:
|
||||||
|
satisfied = False
|
||||||
|
break
|
||||||
|
if not satisfied:
|
||||||
|
continue
|
||||||
|
|
||||||
|
unique_key = tuple(item[u] for u in unique)
|
||||||
|
if unique_key not in results:
|
||||||
|
results[unique_key] = {u: item[u] for u in unique}
|
||||||
|
results[unique_key]["items"] = [item]
|
||||||
|
else:
|
||||||
|
results[unique_key]["items"].append(item)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def fzfill(x, n):
|
||||||
|
if type(x) != str:
|
||||||
|
x = str(round(x, n))
|
||||||
|
return x + "0" * max(0, n - len(x) + 1 + x.find("."))
|
||||||
|
|
||||||
def make_tx_summary(client_logs, server_logs):
|
def make_tx_summary(client_logs, server_logs):
|
||||||
client_results = analyze_logs(client_logs)
|
client_results = analyze_logs(client_logs)
|
||||||
server_results = analyze_logs(server_logs)
|
server_results = analyze_logs(server_logs)
|
||||||
|
|
@ -668,6 +763,7 @@ def make_tx_summary(client_logs, server_logs):
|
||||||
"kex": client["kex"],
|
"kex": client["kex"],
|
||||||
"cipher": client["cipher"],
|
"cipher": client["cipher"],
|
||||||
"ed": client["ed"],
|
"ed": client["ed"],
|
||||||
|
"version": VER_LABEL[client["cipher"]],
|
||||||
"client_impl": client["impl"],
|
"client_impl": client["impl"],
|
||||||
"server_impl": server["impl"],
|
"server_impl": server["impl"],
|
||||||
"plain_energy": plain_energy,
|
"plain_energy": plain_energy,
|
||||||
|
|
@ -689,18 +785,50 @@ def make_tx_summary(client_logs, server_logs):
|
||||||
str(round(tls_only_energy, 2)),
|
str(round(tls_only_energy, 2)),
|
||||||
str(round(tls_rel_energy*100, 2))+"%",
|
str(round(tls_rel_energy*100, 2))+"%",
|
||||||
])
|
])
|
||||||
|
|
||||||
print(tabulate(lines))
|
print(tabulate(lines))
|
||||||
|
|
||||||
|
aggregated = aggregate(txs, ["exp", "record", "alg"], {"server_impl": ["aws-lc"], "client_impl": ["aws-lc"]})
|
||||||
|
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([
|
||||||
|
" ",
|
||||||
|
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{2-8}", ruler=False))
|
||||||
|
|
||||||
def getargv(arg:str, default="", n:int=1, args:list=sys.argv):
|
def getargv(arg:str, default="", n:int=1, args:list=sys.argv):
|
||||||
if arg in args and len(args) > args.index(arg)+n:
|
if arg in args and len(args) > args.index(arg)+n:
|
||||||
return args[args.index(arg)+n]
|
return args[args.index(arg)+n]
|
||||||
else:
|
else:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def parse_logs(logfile_name):
|
||||||
cmd = sys.argv[1]
|
|
||||||
logfile_name = sys.argv[2]
|
|
||||||
logfile = open(logfile_name, "r")
|
logfile = open(logfile_name, "r")
|
||||||
lines = logfile.readlines()
|
lines = logfile.readlines()
|
||||||
logfile.close()
|
logfile.close()
|
||||||
|
|
@ -718,6 +846,14 @@ if __name__ == "__main__":
|
||||||
records[log["record"]] = ()
|
records[log["record"]] = ()
|
||||||
logs.append(log)
|
logs.append(log)
|
||||||
|
|
||||||
|
return (logs, records)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cmd = sys.argv[1]
|
||||||
|
logfile_name = sys.argv[2]
|
||||||
|
|
||||||
|
logs, records = parse_logs(logfile_name)
|
||||||
|
|
||||||
os.makedirs("/dev/shm/plots", exist_ok=True)
|
os.makedirs("/dev/shm/plots", exist_ok=True)
|
||||||
|
|
||||||
no_flamegraph = "-f" in sys.argv
|
no_flamegraph = "-f" in sys.argv
|
||||||
|
|
@ -737,6 +873,26 @@ if __name__ == "__main__":
|
||||||
make_log_plot(logs, "zrtt", "ed", side, "cpu", record, machine=machine, maketitle=maketitle, version="1.3")
|
make_log_plot(logs, "zrtt", "ed", side, "cpu", record, machine=machine, maketitle=maketitle, version="1.3")
|
||||||
make_log_plot(logs, "zrtt", "ed", side, "energy", record, machine=machine, maketitle=maketitle, version="1.3")
|
make_log_plot(logs, "zrtt", "ed", side, "energy", record, machine=machine, maketitle=maketitle, version="1.3")
|
||||||
cmp_versions(logs, ["impl-cipher-ver", "impl-cert-ver", "impl-kex-ver"], ["side", "cipher", "cert", "kex", "record"], ["cpu", "energy"])
|
cmp_versions(logs, ["impl-cipher-ver", "impl-cert-ver", "impl-kex-ver"], ["side", "cipher", "cert", "kex", "record"], ["cpu", "energy"])
|
||||||
|
elif cmd == "log2":
|
||||||
|
# Args: log2 <file1> <target1> [<file2> <target2>] [...]
|
||||||
|
# Only use the intersection of the records
|
||||||
|
logs_by_target = {sys.argv[3]: logs}
|
||||||
|
records_to_remove = {}
|
||||||
|
for i in range(4, len(sys.argv), 2):
|
||||||
|
logs_i, records_i = parse_logs(sys.argv[i])
|
||||||
|
for record in records:
|
||||||
|
if record not in records_i:
|
||||||
|
records_to_remove[record] = ()
|
||||||
|
target_i = sys.argv[i+1]
|
||||||
|
logs_by_target[target_i] = logs_i
|
||||||
|
for record in records_to_remove:
|
||||||
|
records.pop(record)
|
||||||
|
for side in ["client", "server"]:
|
||||||
|
for record in records:
|
||||||
|
make_log_plot_points(logs_by_target, "impl-cipher-ver", "cipher", side, "energy", record)
|
||||||
|
make_log_plot_points(logs_by_target, "impl-cert-ver", "cert", side, "energy", record)
|
||||||
|
make_log_plot_points(logs_by_target, "impl-kex-ver", "kex", side, "energy", record)
|
||||||
|
cmp_versions(logs, ["impl-cipher-ver", "impl-cert-ver", "impl-kex-ver"], ["side", "cipher", "cert", "kex", "record"], ["cpu", "energy"])
|
||||||
elif cmd == "prof":
|
elif cmd == "prof":
|
||||||
for side in ["client", "server"]:
|
for side in ["client", "server"]:
|
||||||
for record in records:
|
for record in records:
|
||||||
|
|
@ -749,7 +905,7 @@ if __name__ == "__main__":
|
||||||
elif cmd == "summary":
|
elif cmd == "summary":
|
||||||
make_summary(logs)
|
make_summary(logs)
|
||||||
elif cmd == "tx":
|
elif cmd == "tx":
|
||||||
logfile_name = sys.argv[2]
|
logfile_name = sys.argv[3]
|
||||||
logfile = open(logfile_name, "r")
|
logfile = open(logfile_name, "r")
|
||||||
lines = logfile.readlines()
|
lines = logfile.readlines()
|
||||||
logfile.close()
|
logfile.close()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue