/ benchmarks / plot.jl
plot.jl
1 #!/usr/bin/env julia 2 3 using Pkg 4 Pkg.activate(@__DIR__) 5 6 using JSON 7 using StatsPlots 8 using Printf 9 using Dates 10 11 function latest_results() 12 files = filter(f -> occursin(r"^results_\d{4}-\d{2}-\d{2}_\d{6}\.json$", f), readdir(@__DIR__)) 13 isempty(files) && error("No results_*.json files found in benchmarks/") 14 sort(files)[end] 15 end 16 17 function load_results(path::String) 18 open(joinpath(@__DIR__, path)) do io 19 return JSON.parse(io) 20 end 21 end 22 23 median_ms(entry) = entry["median_seconds"] * 1e3 24 25 function plot_group(results::Dict, key::Symbol, title::String, labels::Vector{String}, outfile::String) 26 group = get(results, String(key), nothing) 27 group === nothing && return 28 Ns = sort(parse.(Int, collect(keys(group)))) 29 data = [median_ms(group[string(N)][labels[j]]) for j in eachindex(labels), N in Ns] 30 groupedbar(string.(Ns), permutedims(data), bar_position=:dodge, 31 legend=:topleft, title=title, xlabel="N", ylabel="median time (ms)") 32 png(joinpath(@__DIR__, outfile)) 33 end 34 35 function plot_single_ops(results::Dict, key::Symbol, order::Vector{String}, title::String, outfile::String) 36 group = get(results, String(key), nothing) 37 group === nothing && return 38 labels = [label for label in order if haskey(group, label)] 39 values = [median_ms(group[label]) for label in labels] 40 pretty = [replace(label, "_" => " ") for label in labels] 41 bar(pretty, values; legend=false, title=title, ylabel="median time (ms)", xticks=:auto, xrotation=30) 42 png(joinpath(@__DIR__, outfile)) 43 end 44 45 function main() 46 file = length(ARGS) > 0 ? ARGS[1] : latest_results() 47 println("Loading ", file) 48 res = load_results(file) 49 50 # Fixed-base / MSM / normalization 51 plot_group(res, :fixed_g1, "Fixed-base G1 (median)", ["naive", "batch"], "fixed_g1.png") 52 plot_group(res, :fixed_g2, "Fixed-base G2 (median)", ["naive", "batch"], "fixed_g2.png") 53 plot_group(res, :msm_g1, "MSM G1 (median)", ["naive", "msm"], "msm_g1.png") 54 plot_group(res, :msm_g2, "MSM G2 (median)", ["naive", "msm"], "msm_g2.png") 55 plot_group(res, :norm_g1, "Batch norm G1 (median)", ["each", "batch"], "norm_g1.png") 56 plot_group(res, :norm_g2, "Batch norm G2 (median)", ["each", "batch"], "norm_g2.png") 57 58 # Pairing summaries 59 plot_group(res, :pairing, "Pairing sequential vs batch", ["sequential", "batch"], "pairing.png") 60 plot_single_ops(res, :pairing_single, 61 ["pairing", "miller_loop", "final_exponentiation"], 62 "Pairing micro-operations", "pairing_ops.png") 63 64 # Groth16 end-to-end 65 plot_single_ops(res, :groth16, 66 ["r1cs_to_qap", "setup", "prove", "verify_full", "prepare_vk", "prepare_inputs", "verify_prepared"], 67 "Groth16 pipeline", "groth16.png") 68 69 println("Saved plots to benchmarks/*.png") 70 end 71 72 main()