crawl, fixes

This commit is contained in:
Pascal Engélibert 2025-12-19 16:50:56 +01:00
commit f5145f80ea
7 changed files with 326 additions and 58 deletions

113
plots.py
View file

@ -3,20 +3,23 @@ import profile
# Nice labels for algorithms of all kinds
ALG_LABEL = {
"AES_128_GCM_SHA256": "AES128",
"AES_256_GCM_SHA384": "AES256",
"CHACHA20_POLY1305_SHA256": "CHACHA20",
"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "AES128",
"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "AES256",
"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "CHACHA20",
"prime256v1": "prime256v1",
"secp384r1": "secp384r1",
"AES_128_GCM_SHA256": "aes128",
"AES_256_GCM_SHA384": "aes256",
"CHACHA20_POLY1305_SHA256": "chacha20",
"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "aes128",
"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "aes256",
"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "chacha20",
"prime256v1": "p256",
"secp384r1": "p384",
"rsa2048": "rsa2048",
"rsa3072": "rsa3072",
"rsa4096": "rsa4096",
"X25519": "X25519",
"SECP256R1": "SECP256R1",
"SECP384R1": "SECP384R1"
"X25519": "x25519",
"SECP256R1": "p256",
"SECP384R1": "p384",
"X25519MLKEM768": "x25519mlkem",
"SECP256R1MLKEM768": "p256mlkem",
"MLKEM768": "mlkem",
}
# Nice labels for TLS versions using ciphers
@ -56,6 +59,10 @@ CRITERION_TITLE = {
"kex": "key exchange"
}
def impl_title(impl):
# Gnuplot does not escape underscores when generating tex
return impl.replace("_", "-")
# Where gnuplot files, data files and images are output
PLOTS_DIR = "/dev/shm/plots"
@ -87,6 +94,9 @@ set grid y lt 1 lw .75 lc "gray"
plot \
newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using 2:xticlabels(1) notitle col, \
newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using 3:xticlabels(1) title col{cluster}
set term cairolatex pdf
set output "{plots_dir}/{object}_by_{criterion}_{side}_{record}.tex"
replot
""".format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs))
f.close()
os.system("gnuplot {plots_dir}/{object}_by_{criterion}_{side}_{record}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs))
@ -108,14 +118,23 @@ set style fill solid 1.0 border lt -1
set style histogram rowstacked
set style data histograms
set title font "CMU Sans Serif,12" "{object_title} by {criterion_title} ({record}, {side}{machine}) ({unit})"
set xtics border in scale 0,0 nomirror noenhanced rotate by -15 autojustify
set xtics border in scale 0,0 nomirror noenhanced rotate by 30 right
set lmargin 9
set rmargin 1
set bmargin 5
set tmargin 2.5
set key fixed left top vertical Left noenhanced autotitle nobox invert reverse opaque
set colorbox vertical origin screen 0.9, 0.2 size screen 0.05, 0.6 front noinvert bdefault
set xrange [ * : * ] noreverse writeback
set yrange [ 0 : * ]
set grid y lt 1 lw .75 lc "gray"
plot for [i=2:{nb_functions}] "{plots_dir}/{object}_by_{criterion}_{side}_{record}.dat" using i:xticlabels(1) title col
""".format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs))
#set term cairolatex pdf
set term pict2e font ",10"
set output "{plots_dir}/{object}_by_{criterion}_{side}_{record}.tex"
set key font ",10" spacing 0.8
replot
""".format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs).replace("aws_lc", "aws-lc"))
f.close()
os.system("gnuplot {plots_dir}/{object}_by_{criterion}_{side}_{record}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs))
@ -145,19 +164,26 @@ def make_log_plot(logs, exp, criterion, side, obj, record, machine=None):
if log["impl"] not in impls:
impls.append(log["impl"])
impls.sort()
f.write("{} none {}\n".format(criterion, " ".join(impls)))
f.write("{} none {}\n".format(criterion, " ".join([impl_title(impl) for impl in impls])))
f.write(plain_line+" -"*len(impls)+"\n")
for cipher in ciphers:
for impl in impls:
if impl not in ciphers[cipher]:
ciphers[cipher][impl] = 0
f.write("{}({}) - {}\n".format(
"""f.write("{}({}) - {}\n".format(
ALG_LABEL[cipher],
VER_LABEL[log["cipher"]],
" ".join([
str(ciphers[cipher][impl])
for impl in impls
]),
))"""
f.write("{} - {}\n".format(
ALG_LABEL[cipher],
" ".join([
str(ciphers[cipher][impl])
for impl in impls
]),
))
f.close()
gnuplot_histogram(
@ -186,7 +212,7 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m
profile_results = profile.extract_from_file(svg_filename)
except FileNotFoundError:
print(f"Cannot read {svg_filename}")
return
continue
print(profile_results)
for function in profile_results:
if function not in functions:
@ -198,7 +224,7 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m
})
f.write("{} {}\n".format(criterion, " ".join(functions)))
for run in runs:
f.write("\"{} {}({})\" {}\n".format(
"""f.write("\"{} {}({})\" {}\n".format(
run["impl"],
ALG_LABEL[run[criterion]],
VER_LABEL[log["cipher"]],
@ -206,6 +232,14 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m
str(run["functions"][function][0])
for function in functions
]),
))"""
f.write("\"{} {}\" {}\n".format(
impl_title(run["impl"]),
ALG_LABEL[run[criterion]],
" ".join([
str(run["functions"][function][0])
for function in functions
]),
))
f.close()
gnuplot_stacked_histogram(
@ -220,6 +254,46 @@ def make_profile_plot(logs, exp, criterion, side, record, no_flamegraph=False, m
machine=machine
)
# Are CPU and energy proportional
def make_linear_regression(logs):
idle_cpu = None
idle_energy = None
for log in logs:
if log["exp"] == "idle":
idle_cpu = float(log["cpu"]) / float(log["time"])
idle_energy = float(log["Wh"]) / float(log["time"])
break
samples_cpu = {"global":[]}
samples_energy = {"global":[]}
for log in logs:
if log["impl"] == "-":
continue
sample_cpu = float(log["cpu"]) - idle_cpu * float(log["time"])
sample_energy = float(log["Wh"]) - idle_energy * float(log["time"])
samples_cpu["global"].append(sample_cpu)
samples_energy["global"].append(sample_energy)
if log["impl"] not in samples_cpu:
samples_cpu[log["impl"]] = []
samples_energy[log["impl"]] = []
samples_cpu[log["impl"]].append(sample_cpu)
samples_energy[log["impl"]].append(sample_energy)
print("Pearson correlation coefficients (energy/cpu)")
results = {}
for impl in samples_cpu:
res = stats.linregress(samples_cpu[impl], samples_energy[impl])
print(impl, "\t", res.rvalue)
results[impl] = res
if impl != "global":
plt.plot(samples_cpu[impl], samples_energy[impl], 'o', label=impl)
#plt.plot(samples_cpu["global"], samples_energy["global"], 'o', label='samples')
plt.plot(samples_cpu["global"], res.intercept + res.slope*np.array(samples_cpu["global"]), 'r', label='fitted line')
plt.xlabel("CPU (s)")
plt.ylabel("Energy (Wh)")
plt.legend()
#plt.show()
plt.savefig(f"{PLOTS_DIR}/correlation_energy_cpu.png")
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]
@ -267,3 +341,8 @@ if __name__ == "__main__":
make_profile_plot(logs, "impl-cipher-ver", "cipher", side, record, no_flamegraph=no_flamegraph, machine=machine)
make_profile_plot(logs, "impl-cert-ver", "cert", side, record, no_flamegraph=no_flamegraph, machine=machine)
make_profile_plot(logs, "impl-kex-ver", "kex", side, record, no_flamegraph=no_flamegraph, machine=machine)
elif cmd == "correl":
from scipy import stats
import matplotlib.pyplot as plt
import numpy as np
make_linear_regression(logs)