← Back to index

lib/BDD/Behave/Benchmark/Format.rakumod

60 / 61 lines covered (98.4%)

1unit module BDD::Behave::Benchmark::Format;23sub json-string(Str $s --> Str) {4  my $body = $s;5  $body = $body.subst('\\', '\\\\', :g);6  $body = $body.subst('"', '\\"', :g);7  $body = $body.subst("\b", '\\b',  :g);8  $body = $body.subst("\f", '\\f',  :g);9  $body = $body.subst("\n", '\\n',  :g);10  $body = $body.subst("\r", '\\r',  :g);11  $body = $body.subst("\t", '\\t',  :g);12  '"' ~ $body ~ '"';13}1415sub json-number($n --> Str) {16  return 'null' unless $n.defined;17  $n.Real.Str;18}1920our sub to-json($value --> Str) {21  given $value {22    when Bool       { $value ?? 'true' !! 'false' }23    when Numeric    { json-number($value) }24    when Str        { json-string($value) }25    when Positional { '[' ~ $value.list.map(&to-json).join(',') ~ ']' }26    when Associative {27      my @keys = $value.keys.sort;28      '{' ~ @keys.map(-> $k {29        json-string($k.Str) ~ ':' ~ to-json($value{$k})30      }).join(',') ~ '}';31    }32    default {33      return 'null' unless $value.defined;34      json-string($value.Str);35    }36  }37}3839our sub format-bench-summary(@summaries --> Hash) {40  my @rows;41  for @summaries -> %s {42    my $ex = %s<example>;43    @rows.push: {44      description => %s<description>,45      key         => %s<key>,46      label       => (%s<label>    // Str),47      position    => (%s<position> // Int),48      iterations  => %s<iterations>,49      runs        => (%s<runs> // 1),50      min         => %s<min>.Real,51      max         => %s<max>.Real,52      mean        => %s<mean>.Real,53      median      => %s<median>.Real,54      total       => %s<total>.Real,55      file        => ($ex.defined ?? $ex.file.Str !! Str),56      line        => ($ex.defined ?? $ex.line     !! Int),57    };58  }59  %( benchmarks => @rows );60}6162our sub format-bench-regressions(@regressions --> Hash) {63  my @rows;64  for @regressions -> %r {65    @rows.push: {66      description     => %r<description>,67      key             => %r<key>,68      current-median  => %r<median>.Real,69      baseline-median => %r<baseline-median>.Real,70      delta-pct       => %r<delta-pct>.Real,71      regression      => %r<regression>.so,72    };73  }74  %( regressions => @rows );75}7677our sub to-json-document(@summaries, @regressions, Real $threshold --> Str) {78  my %summary    = format-bench-summary(@summaries);79  my %regression = format-bench-regressions(@regressions);80  my %doc = (81    version     => 1,82    threshold   => $threshold.Real,83    benchmarks  => %summary<benchmarks>,84    regressions => %regression<regressions>,85  );86  to-json(%doc);87}8889sub strip-ansi(Str $s --> Str) {90  $s.subst(/\e '[' \d+ 'm'/, '', :g);91}9293our sub visible-width(Str $s --> Int) {94  strip-ansi($s).chars;95}9697our sub pad-right(Str $s, Int $width --> Str) {98  my $pad = $width - visible-width($s);99  $pad > 0 ?? $s ~ (' ' x $pad) !! $s;100}101102our sub pad-left(Str $s, Int $width --> Str) {103  my $pad = $width - visible-width($s);104  $pad > 0 ?? (' ' x $pad) ~ $s !! $s;105}106107our sub render-table(@headers, @rows, @widths, @aligns --> Str) {108  my @lines;109110  my @header-cells;111  for ^@headers.elems -> $i {112    @header-cells.push: @aligns[$i] eq 'right'113      ?? pad-left(@headers[$i], @widths[$i])114      !! pad-right(@headers[$i], @widths[$i]);115  }116  @lines.push: '  ' ~ @header-cells.join('  ');117118  my @rule-cells = @widths.map({ '─' x $_ });119  @lines.push: '  ' ~ @rule-cells.join('  ');120121  for @rows -> @row {122    my @cells;123    for ^@row.elems -> $i {124      @cells.push: @aligns[$i] eq 'right'125        ?? pad-left(@row[$i], @widths[$i])126        !! pad-right(@row[$i], @widths[$i]);127    }128    @lines.push: '  ' ~ @cells.join('  ');129  }130  @lines.join("\n");131}132133our sub column-widths(@headers, @rows --> List) {134  my @widths = @headers.map(&visible-width);135  for @rows -> @row {136    for ^@row.elems -> $i {137      my $w = visible-width(@row[$i]);138      @widths[$i] = $w if $w > @widths[$i];139    }140  }141  @widths.List;142}