Point plots
This commit is contained in:
parent
e98eb7380a
commit
0f52f2813d
2 changed files with 170 additions and 13 deletions
180
plots.py
180
plots.py
|
|
@ -74,7 +74,8 @@ PLOTS_DIR = "/dev/shm/plots"
|
|||
|
||||
# Energy per byte on the network, in W/s
|
||||
# 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):
|
||||
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
|
||||
)
|
||||
|
||||
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):
|
||||
f = open(f"/dev/shm/plots/profile_by_{criterion}_{side}_{record}.dat", "w")
|
||||
runs = []
|
||||
|
|
@ -487,26 +552,26 @@ def cmp_versions(logs, exps, criteria, objs):
|
|||
except ZeroDivisionError:
|
||||
pass
|
||||
|
||||
def tabulate(lines):
|
||||
def tabulate(lines, separator=" ", endline="", ruler=True):
|
||||
widths = [0] * len(lines[0])
|
||||
for line in lines:
|
||||
for col in range(len(line)):
|
||||
if len(line[col]) > widths[col]:
|
||||
widths[col] = len(line[col])
|
||||
table = ""
|
||||
ruler = False
|
||||
ruler_state = False
|
||||
for line in lines:
|
||||
for col in range(len(line)):
|
||||
if col > 0:
|
||||
table += " "
|
||||
table += separator
|
||||
table += line[col]
|
||||
rem = widths[col] - len(line[col])
|
||||
if ruler:
|
||||
if ruler_state:
|
||||
table += " " * (rem % 4) + " · " * (rem // 4)
|
||||
else:
|
||||
table += " " * rem
|
||||
table += "\n"
|
||||
ruler = not ruler
|
||||
table += endline+"\n"
|
||||
ruler_state ^= ruler
|
||||
return table
|
||||
|
||||
def make_summary(logs):
|
||||
|
|
@ -634,6 +699,36 @@ def analyze_logs(logs):
|
|||
})
|
||||
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):
|
||||
client_results = analyze_logs(client_logs)
|
||||
server_results = analyze_logs(server_logs)
|
||||
|
|
@ -668,6 +763,7 @@ def make_tx_summary(client_logs, server_logs):
|
|||
"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,
|
||||
|
|
@ -689,18 +785,50 @@ def make_tx_summary(client_logs, server_logs):
|
|||
str(round(tls_only_energy, 2)),
|
||||
str(round(tls_rel_energy*100, 2))+"%",
|
||||
])
|
||||
|
||||
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):
|
||||
if arg in args and len(args) > args.index(arg)+n:
|
||||
return args[args.index(arg)+n]
|
||||
else:
|
||||
return default
|
||||
|
||||
if __name__ == "__main__":
|
||||
cmd = sys.argv[1]
|
||||
logfile_name = sys.argv[2]
|
||||
def parse_logs(logfile_name):
|
||||
logfile = open(logfile_name, "r")
|
||||
lines = logfile.readlines()
|
||||
logfile.close()
|
||||
|
|
@ -718,6 +846,14 @@ if __name__ == "__main__":
|
|||
records[log["record"]] = ()
|
||||
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)
|
||||
|
||||
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, "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"])
|
||||
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":
|
||||
for side in ["client", "server"]:
|
||||
for record in records:
|
||||
|
|
@ -749,7 +905,7 @@ if __name__ == "__main__":
|
|||
elif cmd == "summary":
|
||||
make_summary(logs)
|
||||
elif cmd == "tx":
|
||||
logfile_name = sys.argv[2]
|
||||
logfile_name = sys.argv[3]
|
||||
logfile = open(logfile_name, "r")
|
||||
lines = logfile.readlines()
|
||||
logfile.close()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue