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 => ResultsDataPruned =>
'Faults summary per benchmark with resulttype, using the pruned data without expansion (resultsdata_pruned.csv)', '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 => TargetClass =>
'Faults by code type with data type (stack/heap/bss/...) and resulttype -> targetclass.csv', '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 { '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; die "No dumps in $local_dump_dir" unless -d $local_dump_dir;
my @dumps = grep { /\.sql$/ } Util::find_files($local_dump_dir); my @dumps = grep { /\.sql$/ } Util::find_files($local_dump_dir);
my @selected_dumps = my @selected_dumps =
@@ -861,135 +864,135 @@ my %handlers = (
'<', Util::shell_quote($dump_file) ); '<', Util::shell_quote($dump_file) );
}, },
'33. Repair fspgroup Write Groups (Mars)' => sub { # '33. Repair fspgroup Write Groups (Mars)' => sub {
#
# Retroactively fixes (hopefully) the missing equivalence class # # Retroactively fixes (hopefully) the missing equivalence class
# mappings (EC <-> Pilot) the BasicPruner misses (because it maps # # mappings (EC <-> Pilot) the BasicPruner misses (because it maps
# multiple classes to a single pilot, but uses the pilot as the # # multiple classes to a single pilot, but uses the pilot as the
# primary key) # # primary key)
my @dbs = Mars::db_list(); # my @dbs = Mars::db_list();
my @dbs_with_notes; # my @dbs_with_notes;
foreach my $db (@dbs) { # foreach my $db (@dbs) {
my $info = # my $info =
Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr ); # Util::read_experiment_info( $db =~ s/smchurla_//r =~ s/:/-/gr );
#
push @dbs_with_notes, # push @dbs_with_notes,
( defined $info && length($info) > 0 ) # ( defined $info && length($info) > 0 )
? sprintf( "%-60s (%s)", $db, $info ) # ? sprintf( "%-60s (%s)", $db, $info )
: $db; # : $db;
} # }
#
my @selected_dbs = TUI::select_from_list( "Select Databases to Repair", # my @selected_dbs = TUI::select_from_list( "Select Databases to Repair",
1, @dbs_with_notes ); # 1, @dbs_with_notes );
die "No database selected" unless @selected_dbs; # die "No database selected" unless @selected_dbs;
#
@selected_dbs = # @selected_dbs =
map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs; # map { s/(.*?)\s+\(.+\)$/$1/r } @selected_dbs;
#
# The PRIMARY KEY gets dropped by the repair and replaced with a KEY. # # 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 # # To not run this shit on already repaired DBs, check for the PRIMARY
# index as a determinant # # index as a determinant
my $index_exists = sub { # my $index_exists = sub {
my ($index) = @_; # my ($index) = @_;
my ($count) = Mars::db_selectrow( # my ($count) = Mars::db_selectrow(
"SELECT COUNT(*) FROM information_schema.STATISTICS # "SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = DATABASE() # WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'fspgroup' # AND TABLE_NAME = 'fspgroup'
AND INDEX_NAME = '$index'" # AND INDEX_NAME = '$index'"
); # );
return $count; # return $count;
}; # };
#
foreach my $db (@selected_dbs) { # foreach my $db (@selected_dbs) {
say "Repairing $db..."; # say "Repairing $db...";
#
# Select the DB so index_exists works # # Select the DB so index_exists works
Mars::db_do("use `$db`"); # Mars::db_do("use `$db`");
#
# Update the variant names, so the queries still work # # Update the variant names, so the queries still work
my $expected_variant = $db =~ s/^smchurla_//r; # my $expected_variant = $db =~ s/^smchurla_//r;
my ($variant_count) = # my ($variant_count) =
Mars::db_selectrow("SELECT COUNT(DISTINCT variant) FROM variant"); # Mars::db_selectrow("SELECT COUNT(DISTINCT variant) FROM variant");
my ($current_variant) = # my ($current_variant) =
Mars::db_selectrow("SELECT DISTINCT variant FROM variant"); # Mars::db_selectrow("SELECT DISTINCT variant FROM variant");
#
if ( !defined $variant_count || $variant_count != 1 ) { # if ( !defined $variant_count || $variant_count != 1 ) {
say " - WARNING: $variant_count distinct variants!"; # say " - WARNING: $variant_count distinct variants!";
} # }
elsif ( $current_variant ne $expected_variant ) { # elsif ( $current_variant ne $expected_variant ) {
say " - Variant is '$current_variant' but queries look up" # say " - Variant is '$current_variant' but queries look up"
. " '$expected_variant' (from the database name), renaming..."; # . " '$expected_variant' (from the database name), renaming...";
Mars::db_do("UPDATE variant SET variant = '$expected_variant'"); # Mars::db_do("UPDATE variant SET variant = '$expected_variant'");
} # }
#
# Drop the primary key # # Drop the primary key
if ( $index_exists->('PRIMARY') ) { # if ( $index_exists->('PRIMARY') ) {
say " - Dropping PRIMARY KEY (pilot_id)..."; # say " - Dropping PRIMARY KEY (pilot_id)...";
Mars::db_do("ALTER TABLE fspgroup DROP PRIMARY KEY"); # Mars::db_do("ALTER TABLE fspgroup DROP PRIMARY KEY");
} # }
#
# Add an index for the columns we actually join on (mostly) # # Add an index for the columns we actually join on (mostly)
unless ( $index_exists->('eq_class') ) { # unless ( $index_exists->('eq_class') ) {
say " - Adding eq_class index..."; # say " - Adding eq_class index...";
Mars::db_do( # Mars::db_do(
"ALTER TABLE fspgroup # "ALTER TABLE fspgroup
ADD KEY eq_class (variant_id, instr2, data_physical_address)" # ADD KEY eq_class (variant_id, instr2, data_physical_address)"
); # );
} # }
#
# I'm currently only using BasicPruner, but don't touch other # # I'm currently only using BasicPruner, but don't touch other
# pruning methods for now, for safety # # pruning methods for now, for safety
my ($fspmethod_id) = # my ($fspmethod_id) =
Mars::db_selectrow( # Mars::db_selectrow(
"SELECT id FROM fspmethod WHERE method = 'basic'"); # "SELECT id FROM fspmethod WHERE method = 'basic'");
die "No 'basic' fspmethod in $db" unless defined $fspmethod_id; # die "No 'basic' fspmethod in $db" unless defined $fspmethod_id;
#
# The first row succeeded before the duplicate key error, remove it # # The first row succeeded before the duplicate key error, remove it
Mars::db_do( # Mars::db_do(
"DELETE g # "DELETE g
FROM fspgroup g # FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id # JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id" # WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
); # );
#
my ($expected) = # my ($expected) =
Mars::db_selectrow( # Mars::db_selectrow(
"SELECT COUNT(*) FROM trace WHERE accesstype = 'W'"); # "SELECT COUNT(*) FROM trace WHERE accesstype = 'W'");
#
# Query from BasicPruner.cc, now ran against the updated DB # # Query from BasicPruner.cc, now ran against the updated DB
say " - Inserting $expected write groups..."; # say " - Inserting $expected write groups...";
Mars::db_do( # Mars::db_do(
"INSERT INTO # "INSERT INTO
fspgroup (variant_id, instr2, data_physical_address, bit_pos, fspmethod_id, pilot_id) # 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 # SELECT STRAIGHT_JOIN t.variant_id, t.instr2, t.data_physical_address, p.bit_pos, p.fspmethod_id, p.id
FROM fsppilot p # FROM fsppilot p
JOIN trace t # JOIN trace t
ON t.variant_id = p.variant_id AND p.fspmethod_id = $fspmethod_id AND p.known_outcome = 1 # ON t.variant_id = p.variant_id AND p.fspmethod_id = $fspmethod_id AND p.known_outcome = 1
WHERE t.accesstype = 'W'" # WHERE t.accesstype = 'W'"
); # );
#
# We expect one row per write group/EC. # # We expect one row per write group/EC.
# Otherwise no idea what's going on :O # # Otherwise no idea what's going on :O
my ($actual) = Mars::db_selectrow( # my ($actual) = Mars::db_selectrow(
"SELECT COUNT(*) # "SELECT COUNT(*)
FROM fspgroup g # FROM fspgroup g
JOIN fsppilot p ON p.id = g.pilot_id # JOIN fsppilot p ON p.id = g.pilot_id
WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id" # WHERE p.known_outcome = 1 AND p.fspmethod_id = $fspmethod_id"
); # );
#
if ( $actual == $expected ) { # if ( $actual == $expected ) {
say " - OK: $actual write groups match the write ECs in trace"; # say " - OK: $actual write groups match the write ECs in trace";
} # }
else { # else {
say " - WARNING: inserted $actual, expected $expected." # say " - WARNING: inserted $actual, expected $expected."
. " Check for duplicate known_outcome pilots:" # . " Check for duplicate known_outcome pilots:"
. " SELECT variant_id, COUNT(*) FROM fsppilot" # . " SELECT variant_id, COUNT(*) FROM fsppilot"
. " WHERE known_outcome = 1 GROUP BY variant_id;"; # . " WHERE known_outcome = 1 GROUP BY variant_id;";
} # }
} # }
#
say "Queries have to be re-run."; # say "Queries have to be re-run.";
}, # },
'95. Delete Builds' => sub { '95. Delete Builds' => sub {