#!/usr/bin/perl -w
#
# extract performances from runs
# output in CSV format

use strict;
use Getopt::Long;

my $threshold;
my $debug = 0;
GetOptions('threshold=f' => \$threshold,
	   'debug' => \$debug)
  or die "unexpected option";

my ($lat, $sdv, $tps, $shared_buffers);

my $i = 0;
my $checkpoints = 0;
my $currentfile = '';

# recompute tps between spikes, from progress output data
sub recompute_tps($\@\@)
{
  die "recompute_tps expecting 3 args" unless @_ == 3;
  my ($threshold, $times, $tps) = @_;

  # detect first and last spikes above threshold
  my ($start, $stop, $on, $prev, $spikes);
  $prev = 0;
  $spikes = 0;
  for my $i (2 .. @{$tps} - 1) {
    # two consecutive mesures above threshold
    $on = (($$tps[$i-1] * ($$times[$i-1] - $$times[$i-2]) >= $threshold) &&
	   ($$tps[$i] * ($$times[$i] - $$times[$i-1]) >= $threshold));
    if ($on and not $prev) {
      $stop = $i - 1;
      $start = $stop unless defined $start;
      $spikes += 1;
    }
    $prev = $on;
  }

  # compute the total number of transactions
  # note that as times are rounded, there may be unexpected effects,
  # and the result is not really an integer
  my $txs = 0;
  for my $i ($start + 1 .. $stop) {
    $txs += $$tps[$i] * ($$times[$i] - $$times[$i-1]);
  }

  my $perf = $txs / ($$times[$stop] - $$times[$start]);
  print STDERR "$start-$stop: $txs ($perf tps on $spikes spikes)\n" if $debug;
  return $perf;
}

my (@times, @tps);

while (<>)
{
  if ($ARGV ne $currentfile) {
    $currentfile = $ARGV;
    $checkpoints = 0;
  }
  # latency average: 3.248 ms
  $lat = $1 if /^latency average: ([0-9\.]+) ms/;
  # latency stddev: 2.840 ms
  $sdv = $1 if /^latency stddev: ([0-9\.]+) ms/;
  # tps = 307.541679 (excluding connections establishing)
  $tps = $1 if /^tps = ([0-9\.]+) \(excluding /;

  # progress: 83.0 s, 1338.9 tps, lat 7.579 ms stddev 16.695
  if (/^progress: (\d+\.\d+) s, (\d+\.\d+) tps,/) {
    push @times, $1;
    push @tps, $2;
  }

  # checkpoints 123
  if (/^# checkpoints: (\d+)/) {
    my $cp = $1 - $checkpoints;
    $checkpoints = $1;
    $i ++;
    my $tps2 = defined($threshold)? recompute_tps($threshold, @times, @tps): $tps;
    print "$i,$tps,$tps2,$lat,$sdv,$cp\n";
    @times = ();
    @tps = ();
  }
}
