NAME Acme::CPANModules::OrderedHash - List of modules that provide ordered hash data type VERSION This document describes version 0.003 of Acme::CPANModules::OrderedHash (from Perl distribution Acme-CPANModules-OrderedHash), released on 2023-10-06. 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 bencher or run "bencher --help". 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: Tie::SortHash - will automatically sort keys when you call keys(), values(), each(). But this module does not maintain insertion order. ACME::CPANMODULES ENTRIES Tie::IxHash Author: CHORNY Hash::Ordered Author: DAGOLDEN Tie::Hash::Indexed Author: MHX Provides two interfaces: tied hash and OO. Tie::LLHash Author: XAERXESS Tie::StoredOrderHash Author: TFM Array::OrdHash Author: WOWASURIN Provide something closest to PHP's associative array, where you can refer elements by key or by numeric index, and insertion order is remembered. List::Unique::DeterministicOrder Author: SLAFFAN Provide a list, not hash. BENCHMARKED MODULES Version numbers shown below are the versions used when running the sample benchmark. Tie::IxHash 1.23 Hash::Ordered 0.014 Tie::Hash::Indexed 0.08 Tie::LLHash 1.004 Tie::StoredOrderHash 0.22 Array::OrdHash 1.03 List::Unique::DeterministicOrder 0.004 BENCHMARK PARTICIPANTS * Tie::IxHash (perl_code) Tie::IxHash * Hash::Ordered (perl_code) Hash::Ordered * Tie::Hash::Indexed (perl_code) Tie::Hash::Indexed * Tie::LLHash (perl_code) Tie::LLHash * Tie::StoredOrderHash (perl_code) Tie::StoredOrderHash * Array::OrdHash (perl_code) Array::OrdHash * List::Unique::DeterministicOrder (perl_code) [no_iterate] List::Unique::DeterministicOrder BENCHMARK DATASETS * insert 1000 pairs * insert 1000 pairs + delete * insert 1000 pairs + return keys 100 times * insert 1000 pairs + iterate 10 times BENCHMARK SAMPLE RESULTS Sample benchmark #1 Run on: perl: *v5.38.0*, CPU: *Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz (2 cores)*, OS: *GNU/Linux Ubuntu version 20.04*, OS kernel: *Linux version 5.4.0-91-generic*. Benchmark command (default options): % bencher --cpanmodules-module OrderedHash Result formatted as table (split, part 1 of 4): #table1# {dataset=>"insert 1000 pairs"} +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | participant | p_tags | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest | errors | samples | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | Tie::StoredOrderHash | | 360 | 2.78 | 0.00% | 197.99% | 1.1e-06 | 20 | | Tie::LLHash | | 380 | 2.6 | 6.60% | 179.55% | 1.3e-05 | 20 | | Array::OrdHash | | 540 | 1.9 | 49.87% | 98.83% | 3.2e-06 | 20 | | Tie::Hash::Indexed | | 700 | 2 | 81.84% | 63.87% | 7.2e-05 | 22 | | Tie::IxHash | | 676 | 1.48 | 87.57% | 58.87% | 9.9e-07 | 20 | | Hash::Ordered | | 884 | 1.13 | 145.25% | 21.50% | 1.1e-06 | 21 | | List::Unique::DeterministicOrder | no_iterate | 1070 | 0.931 | 197.99% | 0.00% | 8e-07 | 21 | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ The above result formatted in Benchmark.pm style: Rate T:S T:L TH:I A:O T:I H:O LU:D no_iterate T:S 360/s -- -6% -28% -31% -46% -59% -66% T:L 380/s 6% -- -23% -26% -43% -56% -64% TH:I 700/s 38% 30% -- -5% -26% -43% -53% A:O 540/s 46% 36% 5% -- -22% -40% -51% T:I 676/s 87% 75% 35% 28% -- -23% -37% H:O 884/s 146% 130% 76% 68% 30% -- -17% LU:D no_iterate 1070/s 198% 179% 114% 104% 58% 21% -- Legends: A:O : p_tags= participant=Array::OrdHash H:O : p_tags= participant=Hash::Ordered LU:D no_iterate: p_tags=no_iterate participant=List::Unique::DeterministicOrder T:I : p_tags= participant=Tie::IxHash T:L : p_tags= participant=Tie::LLHash T:S : p_tags= participant=Tie::StoredOrderHash TH:I : p_tags= participant=Tie::Hash::Indexed The above result presented as chart: Result formatted as table (split, part 2 of 4): #table2# {dataset=>"insert 1000 pairs + delete"} +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | participant | p_tags | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest | errors | samples | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | Tie::IxHash | | 17 | 58.8 | 0.00% | 3799.19% | 4.1e-05 | 20 | | Tie::StoredOrderHash | | 200 | 5 | 1070.77% | 233.04% | 1.1e-05 | 20 | | Tie::LLHash | | 220 | 4.6 | 1191.67% | 201.87% | 1.4e-05 | 21 | | Array::OrdHash | | 279 | 3.59 | 1537.64% | 138.10% | 2.8e-06 | 21 | | Hash::Ordered | | 370 | 2.7 | 2087.76% | 78.23% | 4.9e-06 | 20 | | List::Unique::DeterministicOrder | no_iterate | 604 | 1.66 | 3450.01% | 9.84% | 5.1e-07 | 20 | | Tie::Hash::Indexed | | 663 | 1.51 | 3799.19% | 0.00% | 6e-07 | 20 | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ The above result formatted in Benchmark.pm style: Rate T:I T:S T:L A:O H:O LU:D no_iterate TH:I T:I 17/s -- -91% -92% -93% -95% -97% -97% T:S 200/s 1076% -- -8% -28% -46% -66% -69% T:L 220/s 1178% 8% -- -21% -41% -63% -67% A:O 279/s 1537% 39% 28% -- -24% -53% -57% H:O 370/s 2077% 85% 70% 32% -- -38% -44% LU:D no_iterate 604/s 3442% 201% 177% 116% 62% -- -9% TH:I 663/s 3794% 231% 204% 137% 78% 9% -- Legends: A:O : p_tags= participant=Array::OrdHash H:O : p_tags= participant=Hash::Ordered LU:D no_iterate: p_tags=no_iterate participant=List::Unique::DeterministicOrder T:I : p_tags= participant=Tie::IxHash T:L : p_tags= participant=Tie::LLHash T:S : p_tags= participant=Tie::StoredOrderHash TH:I : p_tags= participant=Tie::Hash::Indexed The above result presented as chart: Result formatted as table (split, part 3 of 4): #table3# {dataset=>"insert 1000 pairs + iterate 10 times"} +----------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | participant | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest | errors | samples | +----------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ | Tie::LLHash | 45 | 22 | 0.00% | 206.84% | 4.1e-05 | 21 | | Tie::StoredOrderHash | 46 | 21.7 | 2.02% | 200.75% | 9.4e-06 | 20 | | Array::OrdHash | 51.4 | 19.5 | 13.93% | 169.32% | 1.4e-05 | 21 | | Tie::IxHash | 65.1 | 15.4 | 44.41% | 112.47% | 9.4e-06 | 20 | | Tie::Hash::Indexed | 97.5 | 10.3 | 116.20% | 41.93% | 9.3e-06 | 20 | | Hash::Ordered | 140 | 7.2 | 206.84% | 0.00% | 6.4e-05 | 20 | +----------------------+-----------+-----------+-----------------------+-----------------------+---------+---------+ The above result formatted in Benchmark.pm style: Rate T:L T:S A:O T:I TH:I H:O T:L 45/s -- -1% -11% -29% -53% -67% T:S 46/s 1% -- -10% -29% -52% -66% A:O 51.4/s 12% 11% -- -21% -47% -63% T:I 65.1/s 42% 40% 26% -- -33% -53% TH:I 97.5/s 113% 110% 89% 49% -- -30% H:O 140/s 205% 201% 170% 113% 43% -- 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 The above result presented as chart: Result formatted as table (split, part 4 of 4): #table4# {dataset=>"insert 1000 pairs + return keys 100 times"} +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+ | participant | p_tags | rate (/s) | time (ms) | pct_faster_vs_slowest | pct_slower_vs_fastest | errors | samples | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+ | Tie::StoredOrderHash | | 10.7 | 93.2 | 0.00% | 845.55% | 5.8e-05 | 20 | | Tie::LLHash | | 12 | 86 | 8.76% | 769.40% | 0.00011 | 20 | | Array::OrdHash | | 14 | 70 | 32.35% | 614.46% | 0.0001 | 20 | | Tie::IxHash | | 16.2 | 61.8 | 50.70% | 527.45% | 5.4e-05 | 20 | | Tie::Hash::Indexed | | 24 | 41 | 124.79% | 320.64% | 0.0001 | 20 | | Hash::Ordered | | 78.3 | 12.8 | 629.18% | 29.67% | 4.2e-06 | 20 | | List::Unique::DeterministicOrder | no_iterate | 101 | 9.85 | 845.55% | 0.00% | 2.2e-06 | 22 | +----------------------------------+------------+-----------+-----------+-----------------------+-----------------------+-----------+---------+ The above result formatted in Benchmark.pm style: Rate T:S T:L A:O T:I TH:I H:O LU:D no_iterate T:S 10.7/s -- -7% -24% -33% -56% -86% -89% T:L 12/s 8% -- -18% -28% -52% -85% -88% A:O 14/s 33% 22% -- -11% -41% -81% -85% T:I 16.2/s 50% 39% 13% -- -33% -79% -84% TH:I 24/s 127% 109% 70% 50% -- -68% -75% H:O 78.3/s 628% 571% 446% 382% 220% -- -23% LU:D no_iterate 101/s 846% 773% 610% 527% 316% 29% -- Legends: A:O : p_tags= participant=Array::OrdHash H:O : p_tags= participant=Hash::Ordered LU:D no_iterate: p_tags=no_iterate participant=List::Unique::DeterministicOrder T:I : p_tags= participant=Tie::IxHash T:L : p_tags= participant=Tie::LLHash T:S : p_tags= participant=Tie::StoredOrderHash TH:I : p_tags= participant=Tie::Hash::Indexed The above result presented as chart: 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 | +----------------------------------+-----------+-------------------+-----------------------+-----------------------+---------+---------+ | List::Unique::DeterministicOrder | 16.2 | 8.5 | 0.00% | 110.26% | 7.7e-06 | 20 | | Hash::Ordered | 15.9 | 8.2 | 1.50% | 107.15% | 6e-06 | 20 | | Tie::Hash::Indexed | 15.5 | 7.8 | 4.57% | 101.06% | 4.9e-06 | 22 | | Array::OrdHash | 15 | 7.3 | 7.86% | 94.94% | 1.1e-05 | 20 | | Tie::IxHash | 14.9 | 7.2 | 8.49% | 93.81% | 9e-06 | 20 | | Tie::LLHash | 13.6 | 5.9 | 18.93% | 76.79% | 7.4e-06 | 20 | | Tie::StoredOrderHash | 10.7 | 3 | 51.34% | 38.93% | 5.9e-06 | 20 | | perl -e1 (baseline) | 7.7 | 0 | 110.26% | 0.00% | 3.4e-05 | 20 | +----------------------------------+-----------+-------------------+-----------------------+-----------------------+---------+---------+ The above result formatted in Benchmark.pm style: Rate LU:D H:O TH:I A:O T:I T:L T:S perl -e1 (baseline) LU:D 61.7/s -- -1% -4% -7% -8% -16% -33% -52% H:O 62.9/s 1% -- -2% -5% -6% -14% -32% -51% TH:I 64.5/s 4% 2% -- -3% -3% -12% -30% -50% A:O 66.7/s 7% 6% 3% -- 0% -9% -28% -48% T:I 67.1/s 8% 6% 4% 0% -- -8% -28% -48% T:L 73.5/s 19% 16% 13% 10% 9% -- -21% -43% T:S 93.5/s 51% 48% 44% 40% 39% 27% -- -28% perl -e1 (baseline) 129.9/s 110% 106% 101% 94% 93% 76% 38% -- Legends: A:O: mod_overhead_time=7.3 participant=Array::OrdHash H:O: mod_overhead_time=8.2 participant=Hash::Ordered LU:D: mod_overhead_time=8.5 participant=List::Unique::DeterministicOrder T:I: mod_overhead_time=7.2 participant=Tie::IxHash T:L: mod_overhead_time=5.9 participant=Tie::LLHash T:S: mod_overhead_time=3 participant=Tie::StoredOrderHash TH:I: mod_overhead_time=7.8 participant=Tie::Hash::Indexed perl -e1 (baseline): mod_overhead_time=0 participant=perl -e1 (baseline) The above result presented as chart: To display as an interactive HTML table on a browser, you can add option "--format html+datatables". BENCHMARK NOTES Hash::Ordered has strong performance in iterating and returning keys, while List::Unique::DeterministicOrder is strong in insertion and deletion (or Tie::Hash::Indexed if you're looking for actual hash type). FAQ 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 Acme::CPANModules for more details. What are ways to use this Acme::CPANModules module? Aside from reading this Acme::CPANModules module's POD documentation, you can install all the listed modules (entries) using cpanm-cpanmodules script (from App::cpanm::cpanmodules distribution): % cpanm-cpanmodules -n OrderedHash Alternatively you can use the cpanmodules CLI (from App::cpanmodules distribution): % cpanmodules ls-entries OrderedHash | cpanm -n or Acme::CM::Get: % perl -MAcme::CM::Get=OrderedHash -E'say $_->{module} for @{ $LIST->{entries} }' | cpanm -n or directly: % perl -MAcme::CPANModules::OrderedHash -E'say $_->{module} for @{ $Acme::CPANModules::OrderedHash::LIST->{entries} }' | cpanm -n This Acme::CPANModules module contains benchmark instructions. You can run a benchmark for some/all the modules listed in this Acme::CPANModules module using the bencher CLI (from Bencher distribution): % bencher --cpanmodules-module OrderedHash This Acme::CPANModules module also helps lcpan produce a more meaningful result for "lcpan related-mods" command when it comes to finding related modules for the modules listed in this Acme::CPANModules module. See App::lcpan::Cmd::related_mods for more details on how "related modules" are found. HOMEPAGE Please visit the project's homepage at . SOURCE Source repository is at . SEE ALSO Acme::CPANModules::HashUtilities Acme::CPANModules - about the Acme::CPANModules namespace cpanmodules - CLI tool to let you browse/view the lists AUTHOR perlancar CONTRIBUTING To contribute, you can send patches by email/via RT, or send pull requests on GitHub. Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via: % prove -l If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond that are considered a bug and can be reported to me. COPYRIGHT AND LICENSE This software is copyright (c) 2023 by perlancar . This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself. BUGS Please report any bugs or feature requests on the bugtracker website 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.