package Bencher::Scenario::SetOperationModules;

our $DATE = '2016-06-26'; # DATE
our $VERSION = '0.09'; # VERSION

use 5.010001;
use strict;
use warnings;

our $scenario = {
    summary => 'Benchmark Perl set operation (union, intersection, diff, symmetric diff) modules',
    modules => {
        'List::MoreUtils' => {
            version => '0.407', # singleton() is available from this version
        },
    },
    participants => [
        # UNION
        {
            tags => ['op:union'],
            module => 'Array::Utils',
            function => 'unique',
            code_template => '&Array::Utils::unique(<set1>, <set2>)', # we use &func instead of func to defeat prototype which confuses some tools
        },
        {
            tags => ['op:union'],
            module => 'Set::Scalar',
            function => 'union',
            code_template => 'my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->union($s2)',
        },
        {
            tags => ['op:union'],
            fcall_template => 'List::MoreUtils::PP::uniq(@{<set1>}, @{<set2>})',
        },
        {
            name => 'List::MoreUtils::XS::uniq',
            tags => ['op:union'],
            module => 'List::MoreUtils::XS',
            fcall_template => 'List::MoreUtils::uniq(@{<set1>}, @{<set2>})',
        },
        {
            tags => ['op:union'],
            fcall_template => 'Array::Set::set_union(<set1>, <set2>)',
        },
        {
            tags => ['op:union'],
            module => 'Set::Array',
            function => 'union',
            code_template => 'my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->union($s2)',
        },
        {
            tags => ['op:union'],
            module => 'Array::AsObject',
            function => 'union',
            code_template => 'my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->union($s2, 1)',
        },
        {
            tags => ['op:union'],
            module => 'Set::Object',
            function => 'union',
            code_template => 'my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->union($s2)',
        },
        {
            tags => ['op:union'],
            module => 'Set::Tiny',
            function => 'union',
            code_template => 'my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->union($s2)',
        },

        # SYMDIFF
        {
            tags => ['op:symdiff'],
            module => 'Array::Utils',
            function => 'array_diff',
            code_template => '&Array::Utils::array_diff(<set1>, <set2>)', # we use &func instead of func to defeat prototype which confuses some tools
        },
        {
            tags => ['op:symdiff'],
            module => 'Set::Scalar',
            function => 'symmetric_difference',
            code_template => 'my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->symmetric_difference($s2)',
        },
        # List::MoreUtils' singleton() can do symmetric difference as long as we
        # make sure that set1 and set2 do not contain duplicates (which, since
        # they should be sets, should not)
        {
            tags => ['op:symdiff'],
            fcall_template => 'List::MoreUtils::PP::singleton(@{<set1>}, @{<set2>})',
        },
        {
            name => 'List::MoreUtils::XS::singleton',
            tags => ['op:symdiff'],
            module => 'List::MoreUtils::XS',
            fcall_template => 'List::MoreUtils::singleton(@{<set1>}, @{<set2>})',
        },
        {
            tags => ['op:symdiff'],
            fcall_template => 'Array::Set::set_symdiff(<set1>, <set2>)',
        },
        {
            tags => ['op:symdiff'],
            module => 'Set::Array',
            function => 'symmetric_difference',
            code_template => 'my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->symmetric_difference($s2)',
        },
        # Array::AsObject::symmetric_difference's handling of duplicates is
        # non-standard though, see its doc
        {
            tags => ['op:symdiff'],
            module => 'Array::AsObject',
            function => 'symmetric_difference',
            code_template => 'my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->symmetric_difference($s2)',
        },
        {
            tags => ['op:symdiff'],
            module => 'Set::Object',
            function => 'symmetric_difference',
            code_template => 'my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->symmetric_difference($s2)',
        },
        {
            tags => ['op:symdiff'],
            module => 'Set::Tiny',
            function => 'symmetric_difference',
            code_template => 'my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->symmetric_difference($s2)',
        },

        # DIFF
        {
            tags => ['op:diff'],
            module => 'Array::Utils',
            function => 'array_minus',
            code_template => '&Array::Utils::array_minus(<set1>, <set2>)', # we use &func instead of func to defeat prototype which confuses some tools
        },
        {
            tags => ['op:diff'],
            module => 'Set::Scalar',
            function => 'difference',
            code_template => 'my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->difference($s2)',
        },
        {
            tags => ['op:diff'],
            fcall_template => 'Array::Set::set_diff(<set1>, <set2>)',
        },
        {
            tags => ['op:diff'],
            module => 'Set::Array',
            function => 'difference',
            code_template => 'my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->difference($s2)',
        },
        # Array::AsObject::difference's handling of duplicates is non-standard
        # though, see its doc
        {
            tags => ['op:diff'],
            module => 'Array::AsObject',
            function => 'difference',
            code_template => 'my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->difference($s2)',
        },
        {
            tags => ['op:diff'],
            module => 'Set::Object',
            function => 'difference',
            code_template => 'my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->difference($s2)',
        },
        {
            tags => ['op:diff'],
            module => 'Set::Tiny',
            function => 'difference',
            code_template => 'my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->difference($s2)',
        },

        # INTERSECT
        {
            tags => ['op:intersect'],
            module => 'Array::Utils',
            function => 'intersect',
            code_template => '&Array::Utils::intersect(<set1>, <set2>)', # we use &func instead of func to defeat prototype which confuses some tools
        },
        {
            tags => ['op:intersect'],
            module => 'Set::Scalar',
            function => 'intersection',
            code_template => 'my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->intersection($s2)',
        },
        # there's no opposite for singleton() yet in List::MoreUtils (as of
        # v0.413).
        {
            tags => ['op:intersect'],
            fcall_template => 'Array::Set::set_intersect(<set1>, <set2>)',
        },
        {
            tags => ['op:intersect'],
            module => 'Set::Array',
            function => 'intersection',
            code_template => 'my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->intersection($s2)',
        },
        {
            tags => ['op:intersect'],
            module => 'Array::AsObject',
            function => 'intersection',
            code_template => 'my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->intersection($s2, 1)',
        },
        {
            tags => ['op:intersect'],
            module => 'Set::Object',
            function => 'intersection',
            code_template => 'my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->intersection($s2)',
        },
        {
            tags => ['op:intersect'],
            module => 'Set::Tiny',
            function => 'intersection',
            code_template => 'my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->intersection($s2)',
        },
    ],

    # XXX: add more datasets (larger data, etc)
    datasets => [
        {
            name => 'num10',
            args => {
                set1 => [1..10],
                set2 => [2..11],
            },
        },
        {
            name => 'num100',
            args => {
                set1 => [1..100],
                set2 => [2..101],
            },
        },
        {
            name => 'num1000',
            args => {
                set1 => [1..1000],
                set2 => [2..1001],
            },
            include_by_default => 0,
        },
    ],
};

1;
# ABSTRACT: Benchmark Perl set operation (union, intersection, diff, symmetric diff) modules

__END__

=pod

=encoding UTF-8

=head1 NAME

Bencher::Scenario::SetOperationModules - Benchmark Perl set operation (union, intersection, diff, symmetric diff) modules

=head1 VERSION

This document describes version 0.09 of Bencher::Scenario::SetOperationModules (from Perl distribution Bencher-Scenario-SetOperationModules), released on 2016-06-26.

=head1 SYNOPSIS

To run benchmark with default option:

 % bencher -m SetOperationModules

To run module startup overhead benchmark:

 % bencher --module-startup -m SetOperationModules

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<Array::AsObject> 1.02

L<Array::Set> 0.02

L<Array::Utils> 0.5

L<List::MoreUtils> 0.413

L<List::MoreUtils::PP> 0.413

L<Set::Array> 0.30

L<Set::Object> 1.35

L<Set::Scalar> 1.29

L<Set::Tiny> 0.04

=head1 BENCHMARK PARTICIPANTS

=over

=item * Array::Utils::unique (perl_code) [op:union]

Code template:

 &Array::Utils::unique(<set1>, <set2>)



=item * Set::Scalar::union (perl_code) [op:union]

Code template:

 my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->union($s2)



=item * List::MoreUtils::PP::uniq (perl_code) [op:union]

Function call template:

 List::MoreUtils::PP::uniq(@{<set1>}, @{<set2>})



=item * List::MoreUtils::XS::uniq (perl_code) [op:union]

Function call template:

 List::MoreUtils::uniq(@{<set1>}, @{<set2>})



=item * Array::Set::set_union (perl_code) [op:union]

Function call template:

 Array::Set::set_union(<set1>, <set2>)



=item * Set::Array::union (perl_code) [op:union]

Code template:

 my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->union($s2)



=item * Array::AsObject::union (perl_code) [op:union]

Code template:

 my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->union($s2, 1)



=item * Set::Object::union (perl_code) [op:union]

Code template:

 my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->union($s2)



=item * Set::Tiny::union (perl_code) [op:union]

Code template:

 my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->union($s2)



=item * Array::Utils::array_diff (perl_code) [op:symdiff]

Code template:

 &Array::Utils::array_diff(<set1>, <set2>)



=item * Set::Scalar::symmetric_difference (perl_code) [op:symdiff]

Code template:

 my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->symmetric_difference($s2)



=item * List::MoreUtils::PP::singleton (perl_code) [op:symdiff]

Function call template:

 List::MoreUtils::PP::singleton(@{<set1>}, @{<set2>})



=item * List::MoreUtils::XS::singleton (perl_code) [op:symdiff]

Function call template:

 List::MoreUtils::singleton(@{<set1>}, @{<set2>})



=item * Array::Set::set_symdiff (perl_code) [op:symdiff]

Function call template:

 Array::Set::set_symdiff(<set1>, <set2>)



=item * Set::Array::symmetric_difference (perl_code) [op:symdiff]

Code template:

 my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->symmetric_difference($s2)



=item * Array::AsObject::symmetric_difference (perl_code) [op:symdiff]

Code template:

 my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->symmetric_difference($s2)



=item * Set::Object::symmetric_difference (perl_code) [op:symdiff]

Code template:

 my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->symmetric_difference($s2)



=item * Set::Tiny::symmetric_difference (perl_code) [op:symdiff]

Code template:

 my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->symmetric_difference($s2)



=item * Array::Utils::array_minus (perl_code) [op:diff]

Code template:

 &Array::Utils::array_minus(<set1>, <set2>)



=item * Set::Scalar::difference (perl_code) [op:diff]

Code template:

 my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->difference($s2)



=item * Array::Set::set_diff (perl_code) [op:diff]

Function call template:

 Array::Set::set_diff(<set1>, <set2>)



=item * Set::Array::difference (perl_code) [op:diff]

Code template:

 my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->difference($s2)



=item * Array::AsObject::difference (perl_code) [op:diff]

Code template:

 my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->difference($s2)



=item * Set::Object::difference (perl_code) [op:diff]

Code template:

 my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->difference($s2)



=item * Set::Tiny::difference (perl_code) [op:diff]

Code template:

 my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->difference($s2)



=item * Array::Utils::intersect (perl_code) [op:intersect]

Code template:

 &Array::Utils::intersect(<set1>, <set2>)



=item * Set::Scalar::intersection (perl_code) [op:intersect]

Code template:

 my $s1 = Set::Scalar->new(@{<set1>}); my $s2 = Set::Scalar->new(@{<set2>}); $s1->intersection($s2)



=item * Array::Set::set_intersect (perl_code) [op:intersect]

Function call template:

 Array::Set::set_intersect(<set1>, <set2>)



=item * Set::Array::intersection (perl_code) [op:intersect]

Code template:

 my $s1 = Set::Array->new(@{<set1>}); my $s2 = Set::Array->new(@{<set2>}); $s1->intersection($s2)



=item * Array::AsObject::intersection (perl_code) [op:intersect]

Code template:

 my $s1 = Array::AsObject->new(@{<set1>}); my $s2 = Array::AsObject->new(@{<set2>}); $s1->intersection($s2, 1)



=item * Set::Object::intersection (perl_code) [op:intersect]

Code template:

 my $s1 = Set::Object->new(@{<set1>}); my $s2 = Set::Object->new(@{<set2>}); $s1->intersection($s2)



=item * Set::Tiny::intersection (perl_code) [op:intersect]

Code template:

 my $s1 = Set::Tiny->new(@{<set1>}); my $s2 = Set::Tiny->new(@{<set2>}); $s1->intersection($s2)



=back

=head1 BENCHMARK DATASETS

=over

=item * num10

=item * num100

=back

=head1 SAMPLE BENCHMARK RESULTS

Run on: perl: I<< v5.22.2 >>, CPU: I<< Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz (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 SetOperationModules >>):

 +---------------------------------------+---------+-----------+-----------+------------+---------+---------+
 | participant                           | dataset | rate (/s) | time (ms) | vs_slowest |  errors | samples |
 +---------------------------------------+---------+-----------+-----------+------------+---------+---------+
 | Array::AsObject::symmetric_difference | num100  |     104.6 | 9.564     |      1     | 9.1e-07 |      20 |
 | Array::AsObject::intersection         | num100  |     213.8 | 4.677     |      2.045 | 4.3e-07 |      20 |
 | Array::AsObject::difference           | num100  |     436   | 2.3       |      4.17  | 2.7e-07 |      20 |
 | Set::Array::intersection              | num100  |     615   | 1.63      |      5.88  | 1.1e-06 |      20 |
 | Array::Set::set_diff                  | num100  |    1400   | 0.713     |     13.4   | 4.3e-07 |      20 |
 | Set::Scalar::intersection             | num100  |    1870   | 0.536     |     17.8   | 2.1e-07 |      20 |
 | Array::Set::set_intersect             | num100  |    1880   | 0.533     |     17.9   | 2.1e-07 |      21 |
 | Array::Set::set_symdiff               | num100  |    1910   | 0.524     |     18.3   | 2.1e-07 |      20 |
 | Set::Scalar::union                    | num100  |    1960   | 0.51      |     18.8   | 2.7e-07 |      20 |
 | Set::Scalar::difference               | num100  |    2050   | 0.487     |     19.6   | 2.4e-07 |      24 |
 | Array::Set::set_union                 | num100  |    2660   | 0.376     |     25.4   | 2.1e-07 |      20 |
 | Set::Scalar::symmetric_difference     | num100  |    2800   | 0.357     |     26.8   | 2.3e-07 |      27 |
 | Array::AsObject::symmetric_difference | num10   |    4690   | 0.213     |     44.9   | 5.3e-08 |      20 |
 | Set::Scalar::intersection             | num10   |   11000   | 0.094     |    100     | 1.1e-07 |      32 |
 | Array::AsObject::intersection         | num10   |   10600   | 0.0942    |    102     | 2.7e-08 |      20 |
 | Set::Scalar::union                    | num10   |   11000   | 0.093     |    100     | 1.1e-07 |      29 |
 | Array::AsObject::union                | num100  |   11000   | 0.091     |    110     | 1.1e-07 |      20 |
 | Set::Scalar::difference               | num10   |   11000   | 0.088     |    110     | 1.1e-07 |      20 |
 | Set::Object::symmetric_difference     | num100  |   11773.7 | 0.0849352 |    112.601 | 9.6e-12 |      20 |
 | Set::Array::difference                | num100  |   12000   | 0.084     |    110     | 1.1e-07 |      31 |
 | Set::Object::intersection             | num100  |   12000   | 0.081     |    120     | 1.1e-07 |      20 |
 | Set::Array::symmetric_difference      | num100  |   13000   | 0.08      |    120     | 1.1e-07 |      20 |
 | Set::Object::union                    | num100  |   14000   | 0.07      |    140     | 2.1e-07 |      20 |
 | Set::Tiny::symmetric_difference       | num100  |   16000   | 0.063     |    150     | 9.5e-08 |      25 |
 | Set::Object::difference               | num100  |   17000   | 0.0589    |    162     | 2.5e-08 |      22 |
 | Array::Set::set_symdiff               | num10   |   17100   | 0.0584    |    164     | 2.4e-08 |      24 |
 | Set::Scalar::symmetric_difference     | num10   |   17200   | 0.058     |    165     | 2.7e-08 |      20 |
 | Set::Tiny::difference                 | num100  |   17000   | 0.058     |    170     | 1.1e-07 |      20 |
 | Set::Tiny::union                      | num100  |   17000   | 0.057     |    170     | 1.1e-07 |      20 |
 | Set::Array::union                     | num100  |   17000   | 0.057     |    170     | 1.1e-07 |      20 |
 | Array::Set::set_intersect             | num10   |   18000   | 0.056     |    170     | 1.1e-07 |      20 |
 | Set::Tiny::intersection               | num100  |   18000   | 0.054     |    180     | 1.1e-07 |      20 |
 | Array::AsObject::difference           | num10   |   21800   | 0.0459    |    208     | 1.1e-08 |      28 |
 | Array::Set::set_union                 | num10   |   24144.1 | 0.0414179 |    230.91  | 1.1e-11 |      20 |
 | List::MoreUtils::PP::singleton        | num100  |   25300   | 0.0395    |    242     | 1.1e-08 |      30 |
 | Array::Utils::array_diff              | num100  |   25806.5 | 0.0387499 |    246.808 |   1e-11 |      21 |
 | Array::Set::set_diff                  | num10   |   28000   | 0.036     |    270     | 3.8e-08 |      22 |
 | Array::Utils::array_minus             | num100  |   29000   | 0.035     |    280     | 4.2e-08 |      33 |
 | Array::Utils::intersect               | num100  |   29300   | 0.0341    |    280     | 3.1e-08 |      33 |
 | List::MoreUtils::PP::uniq             | num100  |   33300   | 0.03      |    319     | 9.9e-09 |      36 |
 | Set::Array::intersection              | num10   |   35471.5 | 0.0281917 |    339.242 |   1e-11 |      20 |
 | List::MoreUtils::XS::singleton        | num100  |   44200   | 0.0226    |    423     | 5.8e-09 |      26 |
 | List::MoreUtils::XS::uniq             | num100  |   56700   | 0.0176    |    542     | 5.8e-09 |      26 |
 | Set::Array::difference                | num10   |   61800   | 0.0162    |    591     | 6.7e-09 |      20 |
 | Set::Array::symmetric_difference      | num10   |   68300   | 0.0146    |    653     | 6.7e-09 |      20 |
 | Set::Object::symmetric_difference     | num10   |   70100   | 0.0143    |    670     | 6.4e-09 |      22 |
 | Array::AsObject::union                | num10   |   72000   | 0.0139    |    689     | 6.1e-09 |      24 |
 | Set::Array::union                     | num10   |   86820.4 | 0.011518  |    830.334 | 9.8e-12 |      22 |
 | Set::Object::intersection             | num10   |  100000   | 0.00996   |    960     | 3.3e-09 |      21 |
 | Set::Object::union                    | num10   |  114000   | 0.00874   |   1090     | 3.3e-09 |      20 |
 | Set::Object::difference               | num10   |  126000   | 0.00797   |   1200     | 2.7e-09 |      30 |
 | Set::Tiny::symmetric_difference       | num10   |  128000   | 0.00782   |   1220     | 7.8e-09 |      33 |
 | Set::Tiny::difference                 | num10   |  138000   | 0.00724   |   1320     | 3.3e-09 |      20 |
 | Set::Tiny::union                      | num10   |  140000   | 0.0069    |   1400     | 7.6e-09 |      35 |
 | Set::Tiny::intersection               | num10   |  150000   | 0.0065    |   1500     | 9.8e-09 |      21 |
 | Array::Utils::array_diff              | num10   |  209380   | 0.0047759 |   2002.5   | 9.5e-12 |      20 |
 | List::MoreUtils::PP::singleton        | num10   |  220000   | 0.0045    |   2100     | 5.5e-09 |      29 |
 | Array::Utils::unique                  | num100  |  235000   | 0.00426   |   2250     | 1.7e-09 |      20 |
 | Array::Utils::array_minus             | num10   |  254190   | 0.003934  |   2431.1   | 9.8e-12 |      20 |
 | Array::Utils::intersect               | num10   |  258200   | 0.003872  |   2470     | 4.7e-11 |      20 |
 | List::MoreUtils::PP::uniq             | num10   |  290000   | 0.0034    |   2800     |   4e-09 |      31 |
 | List::MoreUtils::XS::singleton        | num10   |  400000   | 0.0025    |   3900     | 3.3e-09 |      20 |
 | List::MoreUtils::XS::uniq             | num10   |  501120   | 0.0019955 |   4792.6   | 9.3e-12 |      20 |
 | Array::Utils::unique                  | num10   |  750000   | 0.0013    |   7100     | 1.7e-09 |      20 |
 +---------------------------------------+---------+-----------+-----------+------------+---------+---------+


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

 +---------------------+-----------+------------------------+------------+---------+---------+
 | participant         | time (ms) | mod_overhead_time (ms) | vs_slowest |  errors | samples |
 +---------------------+-----------+------------------------+------------+---------+---------+
 | Set::Array          |      15   |                   12.5 |        1   | 2.1e-05 |      20 |
 | Array::AsObject     |      14   |                   11.5 |        1   | 5.4e-05 |      20 |
 | Set::Object         |      12   |                    9.5 |        1.2 | 2.6e-05 |      21 |
 | Set::Scalar         |      11   |                    8.5 |        1.3 | 3.1e-05 |      20 |
 | List::MoreUtils     |       9.9 |                    7.4 |        1.5 | 3.6e-05 |      21 |
 | Array::Set          |       8.6 |                    6.1 |        1.7 | 1.3e-05 |      20 |
 | List::MoreUtils::PP |       5.5 |                    3   |        2.7 | 1.1e-05 |      20 |
 | Set::Tiny           |       3.8 |                    1.3 |        3.9 | 8.7e-06 |      20 |
 | Array::Utils        |       3.5 |                    1   |        4.2 |   2e-05 |      20 |
 | perl -e1 (baseline) |       2.5 |                    0   |        5.8 |   7e-06 |      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-SetOperationModules>.

=head1 SOURCE

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

=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-SetOperationModules>

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 SEE ALSO

L<Benchmark::Featureset::SetOps>

Excluded modules: L<Set::Bag> (expects hashes instead of arrays),
L<Set::SortedArray> (members are sorted).

=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
