Add alternative resultsdata query that reconstructs fspgroup table instead of depending on it

This commit is contained in:
2026-09-15 15:51:48 +02:00
parent 92cc12d542
commit 9a720d7160
2 changed files with 188 additions and 130 deletions
+55
View File
@@ -0,0 +1,55 @@
package ResultsDataWriteGroups;
use strict;
use warnings;
use diagnostics;
use FindBin;
use lib "$FindBin::Bin/../Modules";
use Filters;
use feature 'say';
sub query {
my ( $experiment, $experiment_dir, @filter_config_names ) = @_;
my $extra =
Filters::build_filter_clause( $experiment_dir, @filter_config_names );
# This query asks the same question as ResultsData.pm: How much faultspace
# area ended up in each possible outcome?
#
# The difference is how the write equivalence classes are treated.
# BasicPruner's write-group INSERT maps every 'W' trace entry to the single
# known_outcome=1 write pilot, but fspgroup has PRIMARY KEY (pilot_id), so
# only the first row lands in the table.
# This query fixes that.
my $querystring = "SELECT
benchmark, resulttype, SUM(t.time2 - t.time1 + 1) AS faults
FROM variant v
JOIN trace t ON v.id = t.variant_id
JOIN fsppilot p ON p.variant_id = t.variant_id
AND ( (p.known_outcome = 1 AND t.accesstype = 'W')
OR (p.known_outcome = 0 AND p.instr2 = t.instr2 AND p.data_physical_address = t.data_physical_address) )
JOIN result_GenericExperimentMessage r ON r.pilot_id = p.id
WHERE v.variant = '$experiment'$extra
GROUP BY v.id, resulttype
ORDER BY variant, benchmark, resulttype;";
say $querystring;
return $querystring;
}
sub args { return "--batch --raw"; }
sub filename {
my @filter_config_names = grep { defined && length } @_;
my $suffix =
@filter_config_names ? "_" . join( "+", sort @filter_config_names ) : "";
return "resultsdata_writegroups${suffix}.csv";
}
sub postprocess { $_[0] =~ s/\t/,/g; }
1;
+133 -130
View File
@@ -100,6 +100,9 @@ my %handlers = (
ResultsDataPruned =>
'Faults summary per benchmark with resulttype, using the pruned data without expansion (resultsdata_pruned.csv)',
ResultsDataWriteGroups =>
'Faults summary per benchmark with resulttype, with write equivalence classes reconstructed from fsppilot (resultsdata_writegroups.csv)',
TargetClass =>
'Faults by code type with data type (stack/heap/bss/...) and resulttype -> targetclass.csv',
@@ -832,7 +835,7 @@ my %handlers = (
'32. Import Database (Mars)' => sub {
# Import databse dump on mars
# Import database dump on mars
die "No dumps in $local_dump_dir" unless -d $local_dump_dir;
my @dumps = grep { /\.sql$/ } Util::find_files($local_dump_dir);
my @selected_dumps =
@@ -861,135 +864,135 @@ my %handlers = (
'<', Util::shell_quote($dump_file) );
},
'33. Repair fspgroup Write Groups (Mars)' => sub {
# Retroactively fixes (hopefully) the missing equivalence class
# mappings (EC <-> Pilot) the BasicPruner misses (because it maps
# multiple classes to a single pilot, but uses the pilot as the
# primary key)
my @dbs = Mars::db_list();
my @dbs_with_notes;
foreach my $db (@dbs) {
my $info =
Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
push @dbs_with_notes,
( defined $info && length($info) > 0 )
? sprintf( "%-60s (%s)", $db, $info )
: $db;
}
my @selected_dbs = TUI::select_from_list( "Select Databases to Repair",
1, @dbs_with_notes );
die "No database selected" unless @selected_dbs;
@selected_dbs =
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
# The PRIMARY KEY gets dropped by the repair and replaced with a KEY.
# To not run this shit on already repaired DBs, check for the PRIMARY
# index as a determinant
my $index_exists = sub {
my ($index) = @_;
my ($count) = Mars::db_selectrow(
"SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'fspgroup'
AND INDEX_NAME = '$index'"
);
return $count;
};
foreach my $db (@selected_dbs) {
say "Repairing $db...";
# Select the DB so index_exists works
Mars::db_do("use `$db`");
# Update the variant names, so the queries still work
my $expected_variant = $db =~ s/^smchurla_//r;
my ($variant_count) =
Mars::db_selectrow("SELECT COUNT(DISTINCT variant) FROM variant");
my ($current_variant) =
Mars::db_selectrow("SELECT DISTINCT variant FROM variant");
if ( !defined $variant_count || $variant_count != 1 ) {
say " - WARNING: $variant_count distinct variants!";
}
elsif ( $current_variant ne $expected_variant ) {
say " - Variant is '$current_variant' but queries look up"
. " '$expected_variant' (from the database name), renaming...";
Mars::db_do("UPDATE variant SET variant = '$expected_variant'");
}
# Drop the primary key
if ( $index_exists->('PRIMARY') ) {
say " - Dropping PRIMARY KEY (pilot_id)...";
Mars::db_do("ALTER TABLE fspgroup DROP PRIMARY KEY");
}
# Add an index for the columns we actually join on (mostly)
unless ( $index_exists->('eq_class') ) {
say " - Adding eq_class index...";
Mars::db_do(
"ALTER TABLE fspgroup
ADD KEY eq_class (variant_id, instr2, data_physical_address)"
);
}
# I'm currently only using BasicPruner, but don't touch other
# pruning methods for now, for safety
my ($fspmethod_id) =
Mars::db_selectrow(
"SELECT id FROM fspmethod WHERE method = 'basic'");
die "No 'basic' fspmethod in $db" unless defined $fspmethod_id;
# The first row succeeded before the duplicate key error, remove it
Mars::db_do(
"DELETE g
FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
);
my ($expected) =
Mars::db_selectrow(
"SELECT COUNT(*) FROM trace WHERE accesstype = 'W'");
# Query from BasicPruner.cc, now ran against the updated DB
say " - Inserting $expected write groups...";
Mars::db_do(
"INSERT INTO
fspgroup (variant_id, instr2, data_physical_address, bit_pos, fspmethod_id, pilot_id)
SELECT STRAIGHT_JOIN t.variant_id, t.instr2, t.data_physical_address, p.bit_pos, p.fspmethod_id, p.id
FROM fsppilot p
JOIN trace t
ON t.variant_id = p.variant_id AND p.fspmethod_id = $fspmethod_id AND p.known_outcome = 1
WHERE t.accesstype = 'W'"
);
# We expect one row per write group/EC.
# Otherwise no idea what's going on :O
my ($actual) = Mars::db_selectrow(
"SELECT COUNT(*)
FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
);
if ( $actual == $expected ) {
say " - OK: $actual write groups match the write ECs in trace";
}
else {
say " - WARNING: inserted $actual, expected $expected."
. " Check for duplicate known_outcome pilots:"
. " SELECT variant_id, COUNT(*) FROM fsppilot"
. " WHERE known_outcome = 1 GROUP BY variant_id;";
}
}
say "Queries have to be re-run.";
},
# '33. Repair fspgroup Write Groups (Mars)' => sub {
#
# # Retroactively fixes (hopefully) the missing equivalence class
# # mappings (EC <-> Pilot) the BasicPruner misses (because it maps
# # multiple classes to a single pilot, but uses the pilot as the
# # primary key)
# my @dbs = Mars::db_list();
# my @dbs_with_notes;
# foreach my $db (@dbs) {
# my $info =
# Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
#
# push @dbs_with_notes,
# ( defined $info && length($info) > 0 )
# ? sprintf( "%-60s (%s)", $db, $info )
# : $db;
# }
#
# my @selected_dbs = TUI::select_from_list( "Select Databases to Repair",
# 1, @dbs_with_notes );
# die "No database selected" unless @selected_dbs;
#
# @selected_dbs =
# map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
#
# # The PRIMARY KEY gets dropped by the repair and replaced with a KEY.
# # To not run this shit on already repaired DBs, check for the PRIMARY
# # index as a determinant
# my $index_exists = sub {
# my ($index) = @_;
# my ($count) = Mars::db_selectrow(
# "SELECT COUNT(*) FROM information_schema.STATISTICS
# WHERE TABLE_SCHEMA = DATABASE()
# AND TABLE_NAME = 'fspgroup'
# AND INDEX_NAME = '$index'"
# );
# return $count;
# };
#
# foreach my $db (@selected_dbs) {
# say "Repairing $db...";
#
# # Select the DB so index_exists works
# Mars::db_do("use `$db`");
#
# # Update the variant names, so the queries still work
# my $expected_variant = $db =~ s/^smchurla_//r;
# my ($variant_count) =
# Mars::db_selectrow("SELECT COUNT(DISTINCT variant) FROM variant");
# my ($current_variant) =
# Mars::db_selectrow("SELECT DISTINCT variant FROM variant");
#
# if ( !defined $variant_count || $variant_count != 1 ) {
# say " - WARNING: $variant_count distinct variants!";
# }
# elsif ( $current_variant ne $expected_variant ) {
# say " - Variant is '$current_variant' but queries look up"
# . " '$expected_variant' (from the database name), renaming...";
# Mars::db_do("UPDATE variant SET variant = '$expected_variant'");
# }
#
# # Drop the primary key
# if ( $index_exists->('PRIMARY') ) {
# say " - Dropping PRIMARY KEY (pilot_id)...";
# Mars::db_do("ALTER TABLE fspgroup DROP PRIMARY KEY");
# }
#
# # Add an index for the columns we actually join on (mostly)
# unless ( $index_exists->('eq_class') ) {
# say " - Adding eq_class index...";
# Mars::db_do(
# "ALTER TABLE fspgroup
# ADD KEY eq_class (variant_id, instr2, data_physical_address)"
# );
# }
#
# # I'm currently only using BasicPruner, but don't touch other
# # pruning methods for now, for safety
# my ($fspmethod_id) =
# Mars::db_selectrow(
# "SELECT id FROM fspmethod WHERE method = 'basic'");
# die "No 'basic' fspmethod in $db" unless defined $fspmethod_id;
#
# # The first row succeeded before the duplicate key error, remove it
# Mars::db_do(
# "DELETE g
# FROM fspgroup g
# JOIN fsppilot p ON p.id = g.pilot_id
# WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
# );
#
# my ($expected) =
# Mars::db_selectrow(
# "SELECT COUNT(*) FROM trace WHERE accesstype = 'W'");
#
# # Query from BasicPruner.cc, now ran against the updated DB
# say " - Inserting $expected write groups...";
# Mars::db_do(
# "INSERT INTO
# fspgroup (variant_id, instr2, data_physical_address, bit_pos, fspmethod_id, pilot_id)
# SELECT STRAIGHT_JOIN t.variant_id, t.instr2, t.data_physical_address, p.bit_pos, p.fspmethod_id, p.id
# FROM fsppilot p
# JOIN trace t
# ON t.variant_id = p.variant_id AND p.fspmethod_id = $fspmethod_id AND p.known_outcome = 1
# WHERE t.accesstype = 'W'"
# );
#
# # We expect one row per write group/EC.
# # Otherwise no idea what's going on :O
# my ($actual) = Mars::db_selectrow(
# "SELECT COUNT(*)
# FROM fspgroup g
# JOIN fsppilot p ON p.id = g.pilot_id
# WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
# );
#
# if ( $actual == $expected ) {
# say " - OK: $actual write groups match the write ECs in trace";
# }
# else {
# say " - WARNING: inserted $actual, expected $expected."
# . " Check for duplicate known_outcome pilots:"
# . " SELECT variant_id, COUNT(*) FROM fsppilot"
# . " WHERE known_outcome = 1 GROUP BY variant_id;";
# }
# }
#
# say "Queries have to be re-run.";
# },
'95. Delete Builds' => sub {