package Bencher::Scenario::SetOperationModules;

our $DATE = '2016-01-05'; # DATE
our $VERSION = '0.08'; # 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

=head1 VERSION

This document describes version 0.08 of Bencher::Scenario::SetOperationModules (from Perl distribution Bencher-Scenario-SetOperationModules), released on 2016-01-05.

=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

L<Array::Utils> 0.5

L<Set::Scalar> 1.29

L<List::MoreUtils::PP> 0.413

L<List::MoreUtils> 0.413

L<Array::Set> 0.02

L<Set::Array> 0.30

L<Array::AsObject> 1.02

L<Set::Object> 1.35

L<Set::Tiny> 0.03

=head1 BENCHMARK PARTICIPANTS

=over

=item * Array::Utils::unique (perl_code)

Code template:

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



=item * Set::Scalar::union (perl_code)

Code template:

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



=item * List::MoreUtils::PP::uniq (perl_code)

Function call template:

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



=item * List::MoreUtils::XS::uniq (perl_code)

Function call template:

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



=item * Array::Set::set_union (perl_code)

Function call template:

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



=item * Set::Array::union (perl_code)

Code template:

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



=item * Array::AsObject::union (perl_code)

Code template:

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



=item * Set::Object::union (perl_code)

Code template:

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



=item * Set::Tiny::union (perl_code)

Code template:

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



=item * Array::Utils::array_diff (perl_code)

Code template:

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



=item * Set::Scalar::symmetric_difference (perl_code)

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)

Function call template:

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



=item * List::MoreUtils::XS::singleton (perl_code)

Function call template:

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



=item * Array::Set::set_symdiff (perl_code)

Function call template:

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



=item * Set::Array::symmetric_difference (perl_code)

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)

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)

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)

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)

Code template:

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



=item * Set::Scalar::difference (perl_code)

Code template:

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



=item * Array::Set::set_diff (perl_code)

Function call template:

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



=item * Set::Array::difference (perl_code)

Code template:

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



=item * Array::AsObject::difference (perl_code)

Code template:

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



=item * Set::Object::difference (perl_code)

Code template:

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



=item * Set::Tiny::difference (perl_code)

Code template:

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



=item * Array::Utils::intersect (perl_code)

Code template:

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



=item * Set::Scalar::intersection (perl_code)

Code template:

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



=item * Array::Set::set_intersect (perl_code)

Function call template:

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



=item * Set::Array::intersection (perl_code)

Code template:

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



=item * Array::AsObject::intersection (perl_code)

Code template:

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



=item * Set::Object::intersection (perl_code)

Code template:

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



=item * Set::Tiny::intersection (perl_code)

Code template:

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



=back

=head1 SAMPLE BENCHMARK RESULTS

Run on: perl: I<< v5.22.0 >>, 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 option:

 +-----+--------------------------------------------------------------------------+------------+--------------+---------+---------+
 | seq | name                                                                     | rate       | time         | errors  | samples |
 +-----+--------------------------------------------------------------------------+------------+--------------+---------+---------+
 | 31  | {dataset=>"num100",participant=>"Array::AsObject::symmetric_difference"} | 57.6       | 17.3ms       | 6.5e-06 | 20      |
 | 59  | {dataset=>"num100",participant=>"Array::AsObject::intersection"}         | 118        | 8.5ms        | 6.2e-06 | 20      |
 | 45  | {dataset=>"num100",participant=>"Array::AsObject::difference"}           | 240        | 4.16ms       | 2.6e-06 | 20      |
 | 57  | {dataset=>"num100",participant=>"Set::Array::intersection"}              | 349        | 2.87ms       | 2.9e-06 | 20      |
 | 41  | {dataset=>"num100",participant=>"Array::Set::set_diff"}                  | 822        | 1.22ms       | 1.1e-06 | 20      |
 | 55  | {dataset=>"num100",participant=>"Array::Set::set_intersect"}             | 1.21e+03   | 0.827ms      | 6.9e-07 | 20      |
 | 27  | {dataset=>"num100",participant=>"Array::Set::set_symdiff"}               | 1.23e+03   | 0.81ms       | 4.8e-07 | 20      |
 | 53  | {dataset=>"num100",participant=>"Set::Scalar::intersection"}             | 1.27e+03   | 0.785ms      | 6.4e-07 | 20      |
 | 3   | {dataset=>"num100",participant=>"Set::Scalar::union"}                    | 1.32e+03   | 0.756ms      | 2.7e-07 | 20      |
 | 39  | {dataset=>"num100",participant=>"Set::Scalar::difference"}               | 1.38e+03   | 0.723ms      | 6.6e-07 | 22      |
 | 9   | {dataset=>"num100",participant=>"Array::Set::set_union"}                 | 1.69e+03   | 0.59ms       | 2.7e-07 | 20      |
 | 21  | {dataset=>"num100",participant=>"Set::Scalar::symmetric_difference"}     | 1.89e+03   | 0.53ms       | 2.7e-07 | 20      |
 | 30  | {dataset=>"num10",participant=>"Array::AsObject::symmetric_difference"}  | 2.58e+03   | 0.387ms      | 2.1e-07 | 20      |
 | 58  | {dataset=>"num10",participant=>"Array::AsObject::intersection"}          | 5.86e+03   | 0.171ms      | 2.1e-07 | 20      |
 | 52  | {dataset=>"num10",participant=>"Set::Scalar::intersection"}              | 6.64e+03   | 0.151ms      | 2.1e-07 | 20      |
 | 2   | {dataset=>"num10",participant=>"Set::Scalar::union"}                     | 6.8e+03    | 0.147ms      | 2.1e-07 | 20      |
 | 38  | {dataset=>"num10",participant=>"Set::Scalar::difference"}                | 7.08e+03   | 0.141ms      | 5.3e-08 | 20      |
 | 13  | {dataset=>"num100",participant=>"Array::AsObject::union"}                | 7.22e+03   | 0.138ms      | 4.6e-08 | 27      |
 | 33  | {dataset=>"num100",participant=>"Set::Object::symmetric_difference"}     | 8.01e+03   | 0.125ms      | 2.1e-07 | 20      |
 | 43  | {dataset=>"num100",participant=>"Set::Array::difference"}                | 8.17e+03   | 0.122ms      | 4.8e-08 | 25      |
 | 29  | {dataset=>"num100",participant=>"Set::Array::symmetric_difference"}      | 8.49e+03   | 0.118ms      | 2.1e-07 | 20      |
 | 61  | {dataset=>"num100",participant=>"Set::Object::intersection"}             | 8.57e+03   | 0.117ms      | 5.3e-08 | 20      |
 | 15  | {dataset=>"num100",participant=>"Set::Object::union"}                    | 9.78e+03   | 0.102ms      | 1.1e-07 | 20      |
 | 26  | {dataset=>"num10",participant=>"Array::Set::set_symdiff"}                | 1.07e+04   | 0.0936ms     | 1.1e-07 | 20      |
 | 20  | {dataset=>"num10",participant=>"Set::Scalar::symmetric_difference"}      | 10751.7    | 0.0930088ms  | 0       | 20      |
 | 54  | {dataset=>"num10",participant=>"Array::Set::set_intersect"}              | 1.1e+04    | 0.0906ms     | 1e-07   | 21      |
 | 35  | {dataset=>"num100",participant=>"Set::Tiny::symmetric_difference"}       | 1.13e+04   | 0.0883ms     | 1.3e-07 | 20      |
 | 11  | {dataset=>"num100",participant=>"Set::Array::union"}                     | 1.17e+04   | 0.0857ms     | 9.9e-08 | 23      |
 | 44  | {dataset=>"num10",participant=>"Array::AsObject::difference"}            | 1.2e+04    | 0.0834ms     | 7.8e-08 | 21      |
 | 47  | {dataset=>"num100",participant=>"Set::Object::difference"}               | 1.24e+04   | 0.0809ms     | 8e-08   | 20      |
 | 49  | {dataset=>"num100",participant=>"Set::Tiny::difference"}                 | 1.27e+04   | 0.079ms      | 1.1e-07 | 20      |
 | 17  | {dataset=>"num100",participant=>"Set::Tiny::union"}                      | 1.27e+04   | 0.0787ms     | 1.1e-07 | 20      |
 | 63  | {dataset=>"num100",participant=>"Set::Tiny::intersection"}               | 1.33e+04   | 0.0753ms     | 1.3e-07 | 22      |
 | 8   | {dataset=>"num10",participant=>"Array::Set::set_union"}                  | 14358.76   | 0.06964389ms | 1.2e-11 | 20      |
 | 40  | {dataset=>"num10",participant=>"Array::Set::set_diff"}                   | 14918.5    | 0.0670308ms  | 0       | 23      |
 | 23  | {dataset=>"num100",participant=>"List::MoreUtils::PP::singleton"}        | 1.8e+04    | 0.0556ms     | 2.3e-08 | 26      |
 | 19  | {dataset=>"num100",participant=>"Array::Utils::array_diff"}              | 1.8e+04    | 0.055ms      | 3e-07   | 23      |
 | 56  | {dataset=>"num10",participant=>"Set::Array::intersection"}               | 1.93e+04   | 0.0519ms     | 2.5e-08 | 23      |
 | 37  | {dataset=>"num100",participant=>"Array::Utils::array_minus"}             | 20417.8    | 0.0489768ms  | 3.5e-11 | 22      |
 | 51  | {dataset=>"num100",participant=>"Array::Utils::intersect"}               | 2.057e+04  | 0.04862ms    | 1.3e-08 | 20      |
 | 5   | {dataset=>"num100",participant=>"List::MoreUtils::PP::uniq"}             | 2.42e+04   | 0.0413ms     | 6.5e-08 | 21      |
 | 25  | {dataset=>"num100",participant=>"List::MoreUtils::XS::singleton"}        | 3.12e+04   | 0.032ms      | 5.3e-08 | 20      |
 | 42  | {dataset=>"num10",participant=>"Set::Array::difference"}                 | 3.44e+04   | 0.0291ms     | 4e-08   | 20      |
 | 28  | {dataset=>"num10",participant=>"Set::Array::symmetric_difference"}       | 3.81e+04   | 0.0262ms     | 1.3e-08 | 21      |
 | 7   | {dataset=>"num100",participant=>"List::MoreUtils::XS::uniq"}             | 4.04e+04   | 0.0248ms     | 3.3e-08 | 21      |
 | 32  | {dataset=>"num10",participant=>"Set::Object::symmetric_difference"}      | 4.223e+04  | 0.02368ms    | 6.5e-09 | 21      |
 | 12  | {dataset=>"num10",participant=>"Array::AsObject::union"}                 | 4.425e+04  | 0.0226ms     | 6.7e-09 | 20      |
 | 10  | {dataset=>"num10",participant=>"Set::Array::union"}                      | 4.7e+04    | 0.0213ms     | 2.7e-08 | 20      |
 | 60  | {dataset=>"num10",participant=>"Set::Object::intersection"}              | 6.07e+04   | 0.0165ms     | 6.5e-09 | 21      |
 | 14  | {dataset=>"num10",participant=>"Set::Object::union"}                     | 7.07e+04   | 0.0141ms     | 2.4e-08 | 25      |
 | 46  | {dataset=>"num10",participant=>"Set::Object::difference"}                | 76941      | 0.012997ms   | 4.6e-11 | 20      |
 | 34  | {dataset=>"num10",participant=>"Set::Tiny::symmetric_difference"}        | 7.86e+04   | 0.0127ms     | 6.7e-09 | 20      |
 | 48  | {dataset=>"num10",participant=>"Set::Tiny::difference"}                  | 8.92e+04   | 0.0112ms     | 1.3e-08 | 20      |
 | 16  | {dataset=>"num10",participant=>"Set::Tiny::union"}                       | 9.59e+04   | 0.0104ms     | 3e-08   | 20      |
 | 62  | {dataset=>"num10",participant=>"Set::Tiny::intersection"}                | 9.868e+04  | 0.01013ms    | 3.2e-09 | 22      |
 | 18  | {dataset=>"num10",participant=>"Array::Utils::array_diff"}               | 1.4e+05    | 0.00713ms    | 3.1e-09 | 23      |
 | 1   | {dataset=>"num100",participant=>"Array::Utils::unique"}                  | 1.56e+05   | 0.0064ms     | 1e-08   | 20      |
 | 22  | {dataset=>"num10",participant=>"List::MoreUtils::PP::singleton"}         | 1.5707e+05 | 0.0063665ms  | 4.6e-11 | 21      |
 | 36  | {dataset=>"num10",participant=>"Array::Utils::array_minus"}              | 1.7408e+05 | 0.0057444ms  | 4.7e-11 | 21      |
 | 50  | {dataset=>"num10",participant=>"Array::Utils::intersect"}                | 1.775e+05  | 0.005633ms   | 1.6e-09 | 21      |
 | 4   | {dataset=>"num10",participant=>"List::MoreUtils::PP::uniq"}              | 2.08e+05   | 0.00482ms    | 1.3e-08 | 21      |
 | 24  | {dataset=>"num10",participant=>"List::MoreUtils::XS::singleton"}         | 2.57e+05   | 0.00389ms    | 6.7e-09 | 20      |
 | 6   | {dataset=>"num10",participant=>"List::MoreUtils::XS::uniq"}              | 3.45e+05   | 0.0029ms     | 3.3e-09 | 20      |
 | 0   | {dataset=>"num10",participant=>"Array::Utils::unique"}                   | 4.81e+05   | 0.00208ms    | 3.3e-09 | 21      |
 +-----+--------------------------------------------------------------------------+------------+--------------+---------+---------+


Benchmark module startup overhead:

 +-----+---------------------+--------+-------------------+---------+---------+
 | seq | name                | time   | mod_overhead_time | errors  | samples |
 +-----+---------------------+--------+-------------------+---------+---------+
 | 7   | Array::AsObject     | 22.3ms | 17ms              | 4.1e-05 | 21      |
 | 6   | Set::Array          | 21.7ms | 16.4ms            | 6.6e-05 | 20      |
 | 8   | Set::Object         | 19ms   | 13ms              | 8e-05   | 20      |
 | 2   | Set::Scalar         | 16.5ms | 11.2ms            | 2.4e-05 | 21      |
 | 4   | List::MoreUtils     | 16ms   | 11ms              | 0.00014 | 20      |
 | 5   | Array::Set          | 13.6ms | 8.25ms            | 2.6e-05 | 20      |
 | 3   | List::MoreUtils::PP | 9.5ms  | 4.2ms             | 3.7e-05 | 20      |
 | 9   | Set::Tiny           | 6.48ms | 1.17ms            | 1.6e-05 | 20      |
 | 1   | Array::Utils        | 6.2ms  | 0.94ms            | 3.4e-05 | 20      |
 | 0   | perl -e1 (baseline) | 5.3ms  | 0ms               | 8.7e-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 SEE ALSO

L<Benchmark::Featureset::SetOps>

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

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