#!/usr/bin/perl # # parse-localbenchmarks - convert localbenchmarks output to CSV # # This is a filter. It transforms data from one format to another. Usage: # # $ make localbenchmarks &> mylogfile # $ hack/parse-localbenchmarks benchmarks.csv # # To be more precise, this is a very stupid simpleminded filter. It is # not a complete solution to the benchmarks problem. In particular, # other tools are still needed to: # # * Actually _run_ the benchmarks in some standard production environment # * Run this script on the results # * Save results, with identifying tags (datetime, git hash, PR id, ...) # * Compare two or more sets of CSVs # (our $ME = $0) =~ s|^.*/||; # script name use v5.14; use utf8; # FIXME: add --help. Some day. Not urgent. die "$ME: This is a filter, not an interactive tool\n" if -t *STDIN; my $n_samples; # Number of timing runs (FIXME: unused) my %results; # Timing results my @benchmarks; # Names of benchmarks my ($type, $testname); # Current context # # Pass 1: read in timings # while (my $line = ) { # Log will have lots of ginkgo output. The only thing we care about is # the summary at the end, which will look something like: # # * [MEASUREMENT] # Podman Benchmark Suite # .... # Ran 3 samples: # [CPU] podman images: # Fastest Time: 0.265s # Slowest Time: 0.322s # Average Time: 0.302s ± 0.018s # [MEM] podman images: # Smallest: 44076.0KB # Largest: 44616.0KB # Average: 44338.7KB ± 171.2KB # [CPU] podman push: # ....repeat [CPU] and [MEM] for each test # -------------------------- # SSSSSSSSSSSSSSSSSSSSS (and more ginkgo output we don't care about) # chomp $line; next unless $line =~ /^.{1,3}\s+\[MEASUREMENT\]/ .. $line =~ /^-{20,}$/; # Trim leading & trailing whitespace $line =~ s/(^\s+|\s+$)//g; # FIXME: we don't actually emit this. What would be a good way to do so? if ($line =~ /^Ran\s+(\d+)\s+samples/) { $n_samples = $1; } # e.g., [CPU] podman foo: elsif ($line =~ /^\[([A-Z]+)\]\s+(\S.*\S):$/) { ($type, $testname) = ($1, $2); } # e.g., 'Fastest Time: 0.265s' elsif ($line =~ /^(\S.*?\S):\s+(.*)/) { my $benchmark = "$type $1"; $results{$testname}{$benchmark} = $2; # Keep an ordered list of benchmark names (as in, the order we # encounter them) push @benchmarks, $benchmark unless grep { $_ eq $benchmark } @benchmarks; } else { warn "Cannot grok '$line'\n" if $ENV{DEBUG_PARSELOCALBENCHMARKS}; } } # # Pass 2: write out CSV # # Headings... print "\"Test Name\""; printf ", \"%s\"", $_ for @benchmarks; print "\n"; # ...then data for my $t (sort keys %results) { printf "\"%s\"", $t; for my $benchmark (@benchmarks) { printf ", \"%s\"", $results{$t}{$benchmark} || ''; } print "\n"; }