package Bencher::Scenario::TextTableModules;

our $DATE = '2016-08-26'; # DATE
our $VERSION = '0.06'; # VERSION

use 5.010001;
use strict;
use warnings;

sub _make_table {
    my ($cols, $rows) = @_;
    my $res = [];
    push @$res, [];
    for (0..$cols-1) { $res->[0][$_] = "col" . ($_+1) }
    for my $row (1..$rows) {
        push @$res, [ map { "row$row.$_" } 1..$cols ];
    }
    $res;
}

our $scenario = {
    summary => 'Benchmark modules that generate text table',
    participants => [
        {
            module => 'Text::ANSITable',
            code => sub {
                my ($table) = @_;
                my $t = Text::ANSITable->new(
                    use_utf8 => 0,
                    use_box_chars => 0,
                    use_color => 0,
                    columns => $table->[0],
                    border_style => 'Default::single_ascii',
                );
                $t->add_row($table->[$_]) for 1..@$table-1;
                $t->draw;
            },
        },
        {
            module => 'Text::ASCIITable',
            code => sub {
                my ($table) = @_;
                my $t = Text::ASCIITable->new();
                $t->setCols(@{ $table->[0] });
                $t->addRow(@{ $table->[$_] }) for 1..@$table-1;
                "$t";
            },
        },
        {
            module => 'Text::FormatTable',
            code => sub {
                my ($table) = @_;
                my $t = Text::FormatTable->new(join('|', ('l') x @{ $table->[0] }));
                $t->head(@{ $table->[0] });
                $t->row(@{ $table->[$_] }) for 1..@$table-1;
                $t->render;
            },
        },
        {
            module => 'Text::MarkdownTable',
            code => sub {
                my ($table) = @_;
                my $out = "";
                my $t = Text::MarkdownTable->new(file => \$out);
                my $fields = $table->[0];
                foreach (1..@$table-1) {
                    my $row = $table->[$_];
                    $t->add( {
                        map { $fields->[$_] => $row->[$_] } 0..@$fields-1
                    });
                }
                $t->done;
                $out;
            },
        },
        {
            module => 'Text::Table',
            code => sub {
                my ($table) = @_;
                my $t = Text::Table->new(@{ $table->[0] });
                $t->load(@{ $table }[1..@$table-1]);
                $t;
            },
        },
        {
            module => 'Text::Table::Tiny',
            code => sub {
                my ($table) = @_;
                Text::Table::Tiny::table(rows=>$table, header_row=>1);
            },
        },
        {
            module => 'Text::Table::Org',
            code => sub {
                my ($table) = @_;
                Text::Table::Org::table(rows=>$table, header_row=>1);
            },
        },
        {
            module => 'Text::Table::CSV',
            code => sub {
                my ($table) = @_;
                Text::Table::CSV::table(rows=>$table, header_row=>1);
            },
        },
        {
            module => 'Text::TabularDisplay',
            code => sub {
                my ($table) = @_;
                my $t = Text::TabularDisplay->new(@{ $table->[0] });
                $t->add(@{ $table->[$_] }) for 1..@$table-1;
                $t->render; # doesn't add newline
            },
        },
    ],

    datasets => [
        {name=>'tiny (1x1)'    , argv => [_make_table( 1, 1)],},
        {name=>'small (3x5)'   , argv => [_make_table( 3, 5)],},
        {name=>'wide (30x5)'   , argv => [_make_table(30, 5)],},
        {name=>'long (3x300)'  , argv => [_make_table( 3, 300)],},
        {name=>'large (30x300)', argv => [_make_table(30, 300)],},
    ],

};

1;
# ABSTRACT: Benchmark modules that generate text table

__END__

=pod

=encoding UTF-8

=head1 NAME

Bencher::Scenario::TextTableModules - Benchmark modules that generate text table

=head1 VERSION

This document describes version 0.06 of Bencher::Scenario::TextTableModules (from Perl distribution Bencher-Scenario-TextTableModules), released on 2016-08-26.

=head1 SYNOPSIS

To run benchmark with default option:

 % bencher -m TextTableModules

To run module startup overhead benchmark:

 % bencher --module-startup -m TextTableModules

For more options (dump scenario, list/include/exclude/add participants, list/include/exclude/add datasets, etc), see L<bencher> or run C<bencher --help>.

=head1 BENCHMARKED MODULES

Version numbers shown below are the versions used when running the sample benchmark.

L<Text::ANSITable> 0.48

L<Text::ASCIITable> 0.20

L<Text::FormatTable> 1.03

L<Text::MarkdownTable> 0.3.1

L<Text::Table> 1.130

L<Text::Table::Tiny> 0.04

L<Text::Table::Org> 0.02

L<Text::Table::CSV> 0.01

L<Text::TabularDisplay> 1.38

=head1 BENCHMARK PARTICIPANTS

=over

=item * Text::ANSITable (perl_code)

L<Text::ANSITable>



=item * Text::ASCIITable (perl_code)

L<Text::ASCIITable>



=item * Text::FormatTable (perl_code)

L<Text::FormatTable>



=item * Text::MarkdownTable (perl_code)

L<Text::MarkdownTable>



=item * Text::Table (perl_code)

L<Text::Table>



=item * Text::Table::Tiny (perl_code)

L<Text::Table::Tiny>



=item * Text::Table::Org (perl_code)

L<Text::Table::Org>



=item * Text::Table::CSV (perl_code)

L<Text::Table::CSV>



=item * Text::TabularDisplay (perl_code)

L<Text::TabularDisplay>



=back

=head1 BENCHMARK DATASETS

=over

=item * tiny (1x1)

=item * small (3x5)

=item * wide (30x5)

=item * long (3x300)

=item * large (30x300)

=back

=head1 SAMPLE BENCHMARK RESULTS

Run on: perl: I<< v5.22.1 >>, CPU: I<< Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz (4 cores) >>, OS: I<< GNU/Linux Debian version 8.0 >>, OS kernel: I<< Linux version 3.16.0-4-amd64 >>.

Benchmark with default options (C<< bencher -m TextTableModules >>):

 #table1#
 {dataset=>"large (30x300)"}
 +----------------------+-----------+-----------+------------+-----------+---------+
 | participant          | rate (/s) | time (ms) | vs_slowest |  errors   | samples |
 +----------------------+-----------+-----------+------------+-----------+---------+
 | Text::ANSITable      |       1.8 |     540   |       1    |   0.00097 |      21 |
 | Text::ASCIITable     |       3.9 |     260   |       2.1  |   0.00042 |      20 |
 | Text::FormatTable    |      10.6 |      94   |       5.77 | 5.3e-05   |      20 |
 | Text::TabularDisplay |      26   |      39   |      14    |   0.00019 |      20 |
 | Text::MarkdownTable  |      63   |      16   |      34    | 2.8e-05   |      20 |
 | Text::Table          |      90   |      11   |      49    | 2.8e-05   |      20 |
 | Text::Table::CSV     |     190   |       5.4 |     100    | 6.9e-06   |      20 |
 | Text::Table::Org     |     210   |       4.7 |     120    | 6.5e-06   |      20 |
 | Text::Table::Tiny    |     240   |       4.1 |     130    | 9.9e-06   |      20 |
 +----------------------+-----------+-----------+------------+-----------+---------+

 #table2#
 {dataset=>"long (3x300)"}
 +----------------------+-----------+-----------+------------+-----------+---------+
 | participant          | rate (/s) | time (ms) | vs_slowest |  errors   | samples |
 +----------------------+-----------+-----------+------------+-----------+---------+
 | Text::ANSITable      |      17   |     60    |       1    |   0.00019 |      20 |
 | Text::ASCIITable     |      37   |     27    |       2.3  | 3.9e-05   |      20 |
 | Text::FormatTable    |      90.2 |     11.1  |       5.45 |   1e-05   |      21 |
 | Text::TabularDisplay |     170   |      6.1  |      10    | 4.4e-05   |      20 |
 | Text::MarkdownTable  |     260   |      3.8  |      16    | 1.3e-05   |      20 |
 | Text::Table          |     340   |      3    |      20    | 3.8e-06   |      20 |
 | Text::Table::CSV     |    1300   |      0.75 |      81    | 1.5e-06   |      20 |
 | Text::Table::Org     |    1500   |      0.69 |      88    | 9.1e-07   |      20 |
 | Text::Table::Tiny    |    1600   |      0.61 |     100    | 2.9e-06   |      20 |
 +----------------------+-----------+-----------+------------+-----------+---------+

 #table3#
 {dataset=>"small (3x5)"}
 +----------------------+-----------+-----------+------------+---------+---------+
 | participant          | rate (/s) | time (μs) | vs_slowest |  errors | samples |
 +----------------------+-----------+-----------+------------+---------+---------+
 | Text::ANSITable      |    695    |  1440     |     1      | 1.3e-06 |      20 |
 | Text::ASCIITable     |   1640    |   609     |     2.36   | 4.8e-07 |      20 |
 | Text::FormatTable    |   4040    |   248     |     5.81   | 2.1e-07 |      20 |
 | Text::Table          |   4900    |   200     |     7.1    | 6.4e-07 |      20 |
 | Text::MarkdownTable  |   7803.32 |   128.151 |    11.2295 | 4.2e-11 |      21 |
 | Text::TabularDisplay |   7900    |   130     |    11      | 1.6e-07 |      20 |
 | Text::Table::Org     |  37000    |    27     |    53      |   4e-08 |      20 |
 | Text::Table::Tiny    |  37000    |    27.1   |    53.2    | 1.3e-08 |      20 |
 | Text::Table::CSV     |  51000    |    19     |    74      | 2.7e-08 |      20 |
 +----------------------+-----------+-----------+------------+---------+---------+

 #table4#
 {dataset=>"tiny (1x1)"}
 +----------------------+-----------+-----------+------------+---------+---------+
 | participant          | rate (/s) | time (μs) | vs_slowest |  errors | samples |
 +----------------------+-----------+-----------+------------+---------+---------+
 | Text::ANSITable      |      2800 |    350    |       1    | 4.8e-07 |      20 |
 | Text::ASCIITable     |      6900 |    150    |       2.4  | 2.1e-07 |      21 |
 | Text::Table          |     13000 |     77    |       4.6  | 2.1e-07 |      20 |
 | Text::MarkdownTable  |     15000 |     65    |       5.4  | 1.1e-07 |      20 |
 | Text::FormatTable    |     19000 |     52    |       6.8  | 1.1e-07 |      20 |
 | Text::TabularDisplay |     31000 |     33    |      11    | 5.3e-08 |      20 |
 | Text::Table::Tiny    |     70000 |     14    |      25    | 8.7e-08 |      20 |
 | Text::Table::Org     |     78010 |     12.82 |      27.39 | 1.5e-10 |      20 |
 | Text::Table::CSV     |    149900 |      6.67 |      52.65 | 2.9e-10 |      26 |
 +----------------------+-----------+-----------+------------+---------+---------+

 #table5#
 {dataset=>"wide (30x5)"}
 +----------------------+-----------+-----------+------------+---------+---------+
 | participant          | rate (/s) | time (ms) | vs_slowest |  errors | samples |
 +----------------------+-----------+-----------+------------+---------+---------+
 | Text::ANSITable      |        79 |     13    |        1   |   3e-05 |      20 |
 | Text::ASCIITable     |       180 |      5.5  |        2.3 | 1.1e-05 |      20 |
 | Text::FormatTable    |       430 |      2.3  |        5.4 | 4.1e-06 |      20 |
 | Text::Table          |       690 |      1.4  |        8.7 | 6.5e-06 |      20 |
 | Text::TabularDisplay |      1300 |      0.76 |       17   | 1.2e-06 |      20 |
 | Text::MarkdownTable  |      2500 |      0.41 |       31   | 9.1e-07 |      20 |
 | Text::Table::Org     |      7200 |      0.14 |       90   | 2.1e-07 |      32 |
 | Text::Table::Tiny    |      8100 |      0.12 |      100   | 2.1e-07 |      20 |
 | Text::Table::CSV     |      8900 |      0.11 |      110   | 2.7e-07 |      20 |
 +----------------------+-----------+-----------+------------+---------+---------+


Benchmark module startup overhead (C<< bencher -m TextTableModules --module-startup >>):

 #table6#
 +----------------------+-----------+------------------------+------------+----------+---------+
 | participant          | time (ms) | mod_overhead_time (ms) | vs_slowest |  errors  | samples |
 +----------------------+-----------+------------------------+------------+----------+---------+
 | Text::ANSITable      |      55   |                   50   |        1   |   0.0001 |      20 |
 | Text::MarkdownTable  |      44   |                   39   |        1.3 | 7.2e-05  |      20 |
 | Text::ASCIITable     |      22   |                   17   |        2.5 | 4.6e-05  |      20 |
 | Text::Table          |      22   |                   17   |        2.5 | 4.9e-05  |      20 |
 | Text::FormatTable    |      13   |                    8   |        4.3 | 4.1e-05  |      20 |
 | Text::Table::Tiny    |      11   |                    6   |        5   | 4.3e-05  |      20 |
 | Text::TabularDisplay |       8.9 |                    3.9 |        6.2 | 1.5e-05  |      20 |
 | Text::Table::Org     |       5.9 |                    0.9 |        9.4 | 3.4e-05  |      21 |
 | perl -e1 (baseline)  |       5   |                    0   |       10   | 8.5e-05  |      20 |
 | Text::Table::CSV     |       5.4 |                    0.4 |       10   | 1.2e-05  |      20 |
 +----------------------+-----------+------------------------+------------+----------+---------+

=head1 DESCRIPTION

Packaging a benchmark script as a Bencher scenario makes it convenient to include/exclude/add participants/datasets (either via CLI or Perl code), send the result to a central repository, among others . See L<Bencher> and L<bencher> (CLI) for more details.

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/Bencher-Scenario-TextTableModules>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-Bencher-Scenario-TextTableModules>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Bencher-Scenario-TextTableModules>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
