Acme-CPANModules-OrderedHash

 view release on metacpan or  search on metacpan

lib/Acme/CPANModules/OrderedHash.pm  view on Meta::CPAN

            },
        },

        {
            module => 'Tree::RB::XS',
            description => <<'MARKDOWN',

Multi-purpose tree data structure which can record insertion order and act as an
ordered hash. Use `track_recent => 1, keys_in_recent_order => 1` options. Can
be used as a tied hash, or as an object (faster).

MARKDOWN
            bench_code => sub {
                my ($op, $numkeys, $numrep) = @_;

                my $tree= Tree::RB::XS->new(compare_fn => 'str', track_recent => 1, keys_in_recent_order => 1);
                for (1..$numkeys) { $tree->insert("key$_") }

                if ($op eq 'delete') {
                    for (1..$numkeys) { $tree->delete("key$_") }
                } elsif ($op eq 'keys') {
                    for (1..$numrep) { my @keys= $tree->keys }
                } elsif ($op eq 'iterate') {
                    for (1..$numrep) { my $iter = $tree->iter; while (my $v = $iter->next) {} }
                }
            },
        },
    ],

    bench_datasets => [
        {name=>'insert 1000 pairs', argv => ['insert', 1000]},
        {name=>'insert 1000 pairs + delete', argv => ['delete', 1000]},
        {name=>'insert 1000 pairs + return keys 100 times', argv => ['keys', 1000, 100]},
        {name=>'insert 1000 pairs + iterate 10 times', argv => ['iterate', 1000, 10], exclude_participant_tags => ['no_iterate']},
    ],
};

1;
# ABSTRACT: List of modules that provide ordered hash data type

__END__

=pod

=encoding UTF-8

=head1 NAME

Acme::CPANModules::OrderedHash - List of modules that provide ordered hash data type

=head1 VERSION

This document describes version 0.004 of Acme::CPANModules::OrderedHash (from Perl distribution Acme-CPANModules-OrderedHash), released on 2025-04-15.

=head1 SYNOPSIS

To run benchmark with default option:

 % bencher --cpanmodules-module OrderedHash

To run module startup overhead benchmark:

 % bencher --module-startup --cpanmodules-module OrderedHash

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 DESCRIPTION

When you ask a Perl's hash for the list of keys, the answer comes back
unordered. In fact, Perl explicitly randomizes the order of keys it returns
everytime. The random ordering is a (security) feature, not a bug. However,
sometimes you want to know the order of insertion. These modules provide you
with an ordered hash; most of them implement it by recording the order of
insertion of keys in an additional array.

Other related modules:

L<Tie::SortHash> - will automatically sort keys when you call C<keys()>,
C<values()>, C<each()>. But this module does not maintain insertion order.

=head1 ACME::CPANMODULES ENTRIES

=over

=item L<Tie::IxHash>

=item L<Hash::Ordered>

=item L<Tie::Hash::Indexed>

Provides two interfaces: tied hash and OO.


=item L<Tie::LLHash>

=item L<Tie::StoredOrderHash>

=item L<Array::OrdHash>

Provide something closest to PHP's associative array, where you can refer
elements by key or by numeric index, and insertion order is remembered.


=item L<List::Unique::DeterministicOrder>

Provide a list, not hash.


=item L<Tree::RB::XS>

Multi-purpose tree data structure which can record insertion order and act as an
ordered hash. Use C<< track_recent =E<gt> 1, keys_in_recent_order =E<gt> 1 >> options. Can
be used as a tied hash, or as an object (faster).


=back

=head1 BENCHMARKED MODULES

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

L<Tie::IxHash> 1.23

lib/Acme/CPANModules/OrderedHash.pm  view on Meta::CPAN

   T:S: participant=Tie::StoredOrderHash
   TH:I: participant=Tie::Hash::Indexed
   TR:X: participant=Tree::RB::XS

The above result presented as chart:

=begin html

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAH4CAMAAABUnipoAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAADJUExURf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

=end html


Result formatted as table (split, part 4 of 4):

 #table4#
 {dataset=>"insert 1000 pairs + return keys 100 times"}
 +----------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+
 | participant          | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors   | samples |
 +----------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+
 | Tie::StoredOrderHash |      17   |     58    |                 0.00% |              1439.14% | 6.1e-05   |      20 |
 | Tie::LLHash          |      20   |     50    |                16.39% |              1222.37% | 7.3e-05   |      20 |
 | Array::OrdHash       |      25   |     40    |                44.54% |               964.81% |   0.00011 |      21 |
 | Tie::IxHash          |      26.8 |     37.3  |                54.99% |               893.08% | 3.3e-05   |      20 |
 | Tie::Hash::Indexed   |      44   |     23    |               154.54% |               504.67% | 2.7e-05   |      20 |
 | Hash::Ordered        |     135   |      7.43 |               678.48% |                97.71% | 7.1e-06   |      20 |
 | Tree::RB::XS         |     270   |      3.8  |              1439.14% |                 0.00% | 4.3e-06   |      20 |
 +----------------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+

The above result formatted in L<Benchmark.pm|Benchmark> style:

          Rate    T:S    T:L   A:O   T:I  TH:I   H:O  TR:X 
  T:S     17/s     --   -13%  -31%  -35%  -60%  -87%  -93% 
  T:L     20/s    15%     --  -19%  -25%  -54%  -85%  -92% 
  A:O     25/s    44%    25%    --   -6%  -42%  -81%  -90% 
  T:I   26.8/s    55%    34%    7%    --  -38%  -80%  -89% 
  TH:I    44/s   152%   117%   73%   62%    --  -67%  -83% 
  H:O    135/s   680%   572%  438%  402%  209%    --  -48% 
  TR:X   270/s  1426%  1215%  952%  881%  505%   95%    -- 
 
 Legends:
   A:O: participant=Array::OrdHash
   H:O: participant=Hash::Ordered
   T:I: participant=Tie::IxHash
   T:L: participant=Tie::LLHash
   T:S: participant=Tie::StoredOrderHash
   TH:I: participant=Tie::Hash::Indexed
   TR:X: participant=Tree::RB::XS

The above result presented as chart:

=begin html

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAH4CAMAAABUnipoAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAADMUExURf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

=end html


=head2 Sample benchmark #2

Benchmark command (benchmarking module startup overhead):

 % bencher --cpanmodules-module OrderedHash --module-startup

Result formatted as table:

 #table5#
 +----------------------+-----------+-------------------+-----------------------+-----------------------+-----------+---------+
 | participant          | time (ms) | mod_overhead_time | pct_faster_vs_slowest | pct_slower_vs_fastest |  errors   | samples |
 +----------------------+-----------+-------------------+-----------------------+-----------------------+-----------+---------+
 | Hash::Ordered        |        14 |                 6 |                 0.00% |                80.85% |   0.00011 |      20 |
 | Tie::Hash::Indexed   |        13 |                 5 |                 3.99% |                73.91% | 9.5e-05   |      21 |
 | Array::OrdHash       |        13 |                 5 |                 9.26% |                65.51% | 9.4e-05   |      20 |
 | Tree::RB::XS         |        12 |                 4 |                 9.34% |                65.39% | 9.6e-05   |      20 |
 | Tie::LLHash          |        12 |                 4 |                12.48% |                60.77% | 8.7e-05   |      20 |
 | Tie::IxHash          |        12 |                 4 |                13.93% |                58.73% | 3.8e-05   |      20 |
 | Tie::StoredOrderHash |        10 |                 2 |                39.06% |                30.05% |   0.0001  |      20 |
 | perl -e1 (baseline)  |         8 |                 0 |                80.85% |                 0.00% | 7.8e-05   |      21 |
 +----------------------+-----------+-------------------+-----------------------+-----------------------+-----------+---------+


The above result formatted in L<Benchmark.pm|Benchmark> style:

                          Rate  H:O  TH:I  A:O  TR:X   T:L   T:I   T:S  perl -e1 (baseline) 
  H:O                   71.4/s   --   -7%  -7%  -14%  -14%  -14%  -28%                 -42% 
  TH:I                  76.9/s   7%    --   0%   -7%   -7%   -7%  -23%                 -38% 
  A:O                   76.9/s   7%    0%   --   -7%   -7%   -7%  -23%                 -38% 
  TR:X                  83.3/s  16%    8%   8%    --    0%    0%  -16%                 -33% 
  T:L                   83.3/s  16%    8%   8%    0%    --    0%  -16%                 -33% 
  T:I                   83.3/s  16%    8%   8%    0%    0%    --  -16%                 -33% 
  T:S                  100.0/s  39%   30%  30%   19%   19%   19%    --                 -19% 
  perl -e1 (baseline)  125.0/s  75%   62%  62%   50%   50%   50%   25%                   -- 
 
 Legends:
   A:O: mod_overhead_time=5 participant=Array::OrdHash
   H:O: mod_overhead_time=6 participant=Hash::Ordered
   T:I: mod_overhead_time=4 participant=Tie::IxHash
   T:L: mod_overhead_time=4 participant=Tie::LLHash
   T:S: mod_overhead_time=2 participant=Tie::StoredOrderHash
   TH:I: mod_overhead_time=5 participant=Tie::Hash::Indexed
   TR:X: mod_overhead_time=4 participant=Tree::RB::XS
   perl -e1 (baseline): mod_overhead_time=0 participant=perl -e1 (baseline)

The above result presented as chart:

=begin html

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAH4CAMAAABUnipoAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAACKUExURf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYAHwYACAAAAAAAAAAAAAAAACYANx...

=end html


To display as an interactive HTML table on a browser, you can add option C<--format html+datatables>.

=head1 FAQ

=head2 What is an Acme::CPANModules::* module?

An Acme::CPANModules::* module, like this module, contains just a list of module
names that share a common characteristics. It is a way to categorize modules and
document CPAN. See L<Acme::CPANModules> for more details.

=head2 What are ways to use this Acme::CPANModules module?



( run in 0.806 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )