From a2746b3f91740b6c98acbe960db9bb5895119a26 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Tue, 1 Sep 2026 01:39:51 +0200 Subject: [PATCH] Add merged fault_probability chart --- .../combined_fault_probability_merged.r | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 scripts/charts/combined_fault_probability_merged.r diff --git a/scripts/charts/combined_fault_probability_merged.r b/scripts/charts/combined_fault_probability_merged.r new file mode 100644 index 0000000..cf19fe3 --- /dev/null +++ b/scripts/charts/combined_fault_probability_merged.r @@ -0,0 +1,117 @@ +library(ggplot2) +library(dplyr) +library(readr) +library(stringr) +library(tidyr) + +# Usage: Rscript combined_fault_probability_merged.r exp_abspath1 ... resultsdata_file + +args <- commandArgs(trailingOnly = TRUE) +if (length(args) < 2) { + stop("Need at least 2 experiments") +} + +csv_suffix <- if (grepl("\\.csv$", args[length(args)])) { + args[length(args)] +} else { + "resultsdata.csv" +} +exp_args <- if (grepl("\\.csv$", args[length(args)])) { + args[-length(args)] +} else { + args +} + +extract_info <- function(path) { + dir_name <- basename(path) + match <- str_match( + dir_name, + "^\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}_(.+?)_(c|aot|interp)_" + ) + if (is.na(match[1, 1])) { + warning(paste("Could not parse:", dir_name)) + return(NULL) + } + + # "tacle-kernel-bsort" -> "bsort", otherwise it doesn't fit + base_name <- sub("^tacle-[^-]+-", "", match[1, 2]) + + list(base_name = base_name, variant = match[1, 3], path = path) +} + +# Load data +all_data <- data.frame() + +for (arg in exp_args) { + info <- extract_info(arg) + if (is.null(info)) { + next + } + + csv_file <- file.path(info$path, csv_suffix) + if (!file.exists(csv_file)) { + warning(paste("Missing:", csv_file)) + next + } + df <- read_csv(csv_file, col_types = cols()) + df$base_name <- info$base_name + df$variant <- info$variant + all_data <- bind_rows(all_data, df) +} + +# TODO: Finally put all the bullshit before this in some shared space + +if (nrow(all_data) == 0) { + stop("No data loaded") +} + +marker_order <- c( + "OK_MARKER", + "DETECTED_MARKER", + "GROUP1_MARKER", + "TRAP", + "TIMEOUT", + "WRITE_TEXTSEGMENT", + "ACCESS_OUTERSPACE", + "FAIL_MARKER" +) + +# Merge ip/mem/regs, then divide by the merged faultspace area +# Don't merge GROUP1_MARKER into TRAP for this chart +# Also keep the OK_MARKERs, so the "sum to 100%" is accurate +probability <- all_data |> + group_by(base_name, variant, resulttype) |> + summarise(faults = sum(faults, na.rm = TRUE), .groups = "drop") |> + group_by(base_name, variant) |> + mutate(frac = faults / sum(faults, na.rm = TRUE)) |> + ungroup() + +# Don't print alphabetically +probability$resulttype <- factor(probability$resulttype, levels = marker_order) +probability$variant <- factor( + probability$variant, + levels = c("c", "aot", "interp") +) + +plot <- ggplot( + probability, + aes(x = variant, y = frac, fill = resulttype) +) + + geom_col() + + facet_wrap(~base_name) + + scale_y_continuous(labels = scales::percent) + + labs( + title = "Fault Probability (merged ip + mem + regs)", + x = NULL, + y = "Probability of Failure", + fill = "Fault Type" + ) + + theme_minimal() + + theme( + plot.title = element_text(size = 13, face = "bold"), + axis.text.x = element_text(angle = 45, hjust = 1) + ) + +out_suffix <- gsub("^resultsdata|\\.csv$", "", csv_suffix) +filename <- paste0("injections/fault_probability_merged", out_suffix, ".svg") +ggsave(filename, plot = plot, width = 13, height = 8)