1 <section xmlns="http://docbook.org/ns/docbook" version="5.0"
2 xml:id="pbds.test" xreflabel="Test">
3 <info><title>Testing</title></info>
4 <?dbhtml filename="policy_based_data_structures_test.html"?>
6 <!-- S01 regression -->
7 <section xml:id="pbds.test.regression">
8 <info><title>Regression</title></info>
10 <para>The library contains a single comprehensive regression test.
11 For a given container type in this library, the test creates
12 an object of the container type and an object of the
13 corresponding standard type (e.g., <classname>std::set</classname>). It
14 then performs a random sequence of methods with random
15 arguments (e.g., inserts, erases, and so forth) on both
16 objects. At each operation, the test checks the return value of
17 the method, and optionally both compares this library's
18 object with the standard's object as well as performing other
19 consistency checks on this library's object (e.g.,
20 order preservation, when applicable, or node invariants, when
23 <para>Additionally, the test integrally checks exception safety
24 and resource leaks. This is done as follows. A special
25 allocator type, written for the purpose of the test, both
26 randomly throws an exceptions when allocations are performed,
27 and tracks allocations and de-allocations. The exceptions thrown
28 at allocations simulate memory-allocation failures; the
29 tracking mechanism checks for memory-related bugs (e.g.,
30 resource leaks and multiple de-allocations). Both
31 this library's containers and the containers' value-types are
32 configured to use this allocator.</para>
34 <para>For granularity, the test is split into the
35 several sources, each checking only some containers.</para>
37 <para>For more details, consult the files in
38 <filename class="directory">testsuite/ext/pb_ds/regression</filename>.
42 <!-- S02 performance -->
43 <section xml:id="pbds.test.performance">
44 <info><title>Performance</title></info>
46 <section xml:id="performance.hash">
47 <info><title>Hash-Based</title></info>
50 <!-- 01 <a href="hash_text_find_find_timing_test"> -->
51 <section xml:id="performance.hash.text_find">
53 Text <function>find</function>
57 <section xml:id="hash.text_find.info">
63 This test inserts a number of values with keys from an
65 linkend="biblio.wickland96thirty"/>) into a container,
66 then performs a series of finds using
67 <function>find</function> . It measures the average
68 time for <function>find</function> as a function of
69 the number of values inserted.</para>
71 It uses the test file:
72 <filename>performance/ext/pb_ds/text_find_timing_test.cc</filename>
76 And uses the data file:
77 <filename>filethirty_years_among_the_dead_preproc.txt</filename>
80 <para>The test checks the effect of different range-hashing
81 functions, trigger policies, and cache-hashing policies.
86 <section xml:id="hash.text_find.results">
91 <para>The graphic below show the results for the native
92 and collision-chaining hash types the function
93 applied being a text find timing test using
94 <function>find</function>.
97 <!-- results graphic -->
101 <imagedata align="center" format="PDF" scale="75"
102 fileref="../images/pbds_hash_text_find.pdf"/>
105 <imagedata align="center" format="PNG" scale="100"
106 fileref="../images/pbds_hash_text_find.png"/>
112 The abbreviated names in the legend of the graphic above are
113 instantiated with the types in the following table.
117 <informaltable frame="all">
119 <tgroup cols="5" align="left" colsep="1" rowsep="1">
120 <colspec colname="c1"/>
121 <colspec colname="c2"/>
122 <colspec colname="c3"/>
123 <colspec colname="c4"/>
124 <colspec colname="c5"/>
127 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
128 <entry><emphasis>Parameter</emphasis></entry>
129 <entry><emphasis>Details</emphasis></entry>
130 <entry><emphasis>Parameter</emphasis></entry>
131 <entry><emphasis>Details</emphasis></entry>
139 <?dbhtml bgcolor="#B0B0B0" ?>
140 <entry namest="c1" nameend="c5">
147 <classname>std::tr1::unordered_map</classname>
150 <classname>cache_hash_code</classname>
153 <constant>false</constant>
155 <entry namest="c4" nameend="c5"></entry>
160 <?dbhtml bgcolor="#B0B0B0" ?>
161 <entry namest="c1" nameend="c5">
162 cc_hash_mod_prime_1div1_nsth_map
167 <entry morerows="2" valign="top">
168 <classname>cc_hash_table</classname>
171 <classname>Comb_Hash_Fn</classname>
174 <classname>direct_mod_range_hashing</classname>
176 <entry namest="c4" nameend="c5"></entry>
180 <entry morerows="1" valign="top">
181 <classname>Resize_Policy</classname>
183 <entry morerows="1" valign="top">
184 <classname>hash_standard_resize_policy</classname>
187 <classname>Size_Policy</classname>
190 <classname>hash_prime_size_policy</classname>
196 <classname>Trigger_Policy</classname>
199 <classname>hash_load_check_resize_trigger</classname> with
200 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
206 <?dbhtml bgcolor="#B0B0B0" ?>
207 <entry namest="c1" nameend="c5">
208 cc_hash_mask_exp_1div2_sth_map
213 <entry morerows="2" valign="top">
219 <classname>Comb_Hash_Fn</classname>
222 <classname>direct_mask_range_hashing</classname>
224 <entry namest="c4" nameend="c5"></entry>
228 <entry morerows="1" valign="top">
229 <classname>Resize_Policy</classname>
231 <entry morerows="1" valign="top">
232 <classname>hash_standard_resize_policy</classname>
235 <classname>Size_Policy</classname>
238 <classname>hash_exponential_size_policy</classname>
244 <classname>Trigger_Policy</classname>
247 <classname>hash_load_check_resize_trigger</classname> with
248 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
254 <?dbhtml bgcolor="#B0B0B0" ?>
255 <entry namest="c1" nameend="c5">
256 cc_hash_mask_exp_1div1_nsth_map
261 <entry morerows="2" valign="top">
262 <classname>cc_hash_table</classname>
265 <classname>Comb_Hash_Fn</classname>
268 <classname>direct_mask_range_hashing</classname>
270 <entry namest="c4" nameend="c5"></entry>
274 <entry morerows="1" valign="top">
275 <classname>Resize_Policy</classname>
277 <entry morerows="1" valign="top">
278 <classname>hash_standard_resize_policy</classname>
281 <classname>Size_Policy</classname>
284 <classname>hash_exponential_size_policy</classname>
290 <classname>Trigger_Policy</classname>
293 <classname>hash_load_check_resize_trigger</classname> with
294 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
300 <?dbhtml bgcolor="#B0B0B0" ?>
301 <entry namest="c1" nameend="c5">
302 cc_hash_mask_exp_1div2_nsth_map
306 <entry morerows="2" valign="top">
307 <classname>cc_hash_table</classname>
310 <classname>Comb_Hash_Fn</classname>
313 <classname>direct_mask_range_hashing</classname>
315 <entry namest="c4" nameend="c5"></entry>
319 <entry morerows="1" valign="top">
320 <classname>Resize_Policy</classname>
322 <entry morerows="1" valign="top">
323 <classname>hash_standard_resize_policy</classname>
326 <classname>Size_Policy</classname>
329 <classname>hash_exponential_size_policy</classname>
335 <classname>Trigger_Policy</classname>
338 <classname>hash_load_check_resize_trigger</classname> with
339 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
349 <section xml:id="hash.text_find.observations">
354 <para>In this setting, the range-hashing scheme affects performance
355 more than other policies. As the results show, containers using
356 mod-based range-hashing (including the native hash-based container,
357 which is currently hard-wired to this scheme) have lower performance
358 than those using mask-based range-hashing. A modulo-based
359 range-hashing scheme's main benefit is that it takes into account
360 all hash-value bits. Standard string hash-functions are designed to
361 create hash values that are nearly-uniform as is (<xref
362 linkend="biblio.knuth98sorting"/>).</para>
364 <para>Trigger policies, i.e. the load-checks constants, affect
365 performance to a lesser extent.</para>
367 <para>Perhaps surprisingly, storing the hash value alongside each
368 entry affects performance only marginally, at least in this
369 library's implementation. (Unfortunately, it was not possible to run
370 the tests with <classname>std::tr1::unordered_map</classname> 's
371 <classname>cache_hash_code = true</classname> , as it appeared to
378 <!-- 02 <a href="hash_int_find_timing_test"> -->
379 <section xml:id="performance.hash.int_find">
381 Integer <function>find</function>
385 <section xml:id="hash.int_find.info">
390 <para>This test inserts a number of values with uniform
391 integer keys into a container, then performs a series of finds
392 using <function>find</function>. It measures the average time
393 for <function>find</function> as a function of the number of values
397 It uses the test file:
398 <filename>performance/ext/pb_ds/random_int_find_timing.cc</filename>
401 <para>The test checks the effect of different underlying
403 range-hashing functions, and trigger policies.</para>
407 <section xml:id="hash.int_find.results">
413 There are two sets of results for this type, one for
414 collision-chaining hashes, and one for general-probe hashes.
417 <para>The first graphic below shows the results for the native and
418 collision-chaining hash types. The function applied being a random
419 integer timing test using <function>find</function>.
422 <!-- results graphic 01 -->
426 <imagedata align="center" format="PDF" scale="75"
427 fileref="../images/pbds_cc_hash_int_find.pdf"/>
430 <imagedata align="center" format="PNG" scale="100"
431 fileref="../images/pbds_cc_hash_int_find.png"/>
437 The abbreviated names in the legend of the graphic above are
438 instantiated with the types in the following table.
442 <informaltable frame="all">
444 <tgroup cols="5" align="left" colsep="1" rowsep="1">
445 <colspec colname="c1"/>
446 <colspec colname="c2"/>
447 <colspec colname="c3"/>
448 <colspec colname="c4"/>
449 <colspec colname="c5"/>
452 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
453 <entry><emphasis>Parameter</emphasis></entry>
454 <entry><emphasis>Details</emphasis></entry>
455 <entry><emphasis>Parameter</emphasis></entry>
456 <entry><emphasis>Details</emphasis></entry>
464 <?dbhtml bgcolor="#B0B0B0" ?>
465 <entry namest="c1" nameend="c5">
472 <classname>std::tr1::unordered_map</classname>
475 <classname>cache_hash_code</classname>
478 <constant>false</constant>
480 <entry namest="c4" nameend="c5"></entry>
485 <?dbhtml bgcolor="#B0B0B0" ?>
486 <entry namest="c1" nameend="c5">
487 cc_hash_mod_prime_1div1_nsth_map
492 <entry morerows="2" valign="top">
493 <classname>cc_hash_table</classname>
496 <classname>Comb_Hash_Fn</classname>
499 <classname>direct_mod_range_hashing</classname>
501 <entry namest="c4" nameend="c5"></entry>
505 <entry morerows="1" valign="top">
506 <classname>Resize_Policy</classname>
508 <entry morerows="1" valign="top">
509 <classname>hash_standard_resize_policy</classname>
512 <classname>Size_Policy</classname>
515 <classname>hash_prime_size_policy</classname>
521 <classname>Trigger_Policy</classname>
524 <classname>hash_load_check_resize_trigger</classname> with
525 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
531 <?dbhtml bgcolor="#B0B0B0" ?>
532 <entry namest="c1" nameend="c5">
533 cc_hash_mod_prime_1div2_nsth_map
538 <entry morerows="2" valign="top">
544 <classname>Comb_Hash_Fn</classname>
547 <classname>direct_mod_range_hashing</classname>
549 <entry namest="c4" nameend="c5"></entry>
553 <entry morerows="1" valign="top">
554 <classname>Resize_Policy</classname>
556 <entry morerows="1" valign="top">
557 <classname>hash_standard_resize_policy</classname>
560 <classname>Size_Policy</classname>
563 <classname>hash_prime_size_policy</classname>
569 <classname>Trigger_Policy</classname>
572 <classname>hash_load_check_resize_trigger</classname> with
573 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
579 <?dbhtml bgcolor="#B0B0B0" ?>
580 <entry namest="c1" nameend="c5">
581 cc_hash_mask_exp_1div1_nsth_map
586 <entry morerows="2" valign="top">
587 <classname>cc_hash_table</classname>
590 <classname>Comb_Hash_Fn</classname>
593 <classname>direct_mask_range_hashing</classname>
595 <entry namest="c4" nameend="c5"></entry>
599 <entry morerows="1" valign="top">
600 <classname>Resize_Policy</classname>
602 <entry morerows="1" valign="top">
603 <classname>hash_standard_resize_policy</classname>
606 <classname>Size_Policy</classname>
609 <classname>hash_exponential_size_policy</classname>
615 <classname>Trigger_Policy</classname>
618 <classname>hash_load_check_resize_trigger</classname> with
619 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
625 <?dbhtml bgcolor="#B0B0B0" ?>
626 <entry namest="c1" nameend="c5">
627 cc_hash_mask_exp_1div2_nsth_map
631 <entry morerows="2" valign="top">
632 <classname>cc_hash_table</classname>
635 <classname>Comb_Hash_Fn</classname>
638 <classname>direct_mask_range_hashing</classname>
640 <entry namest="c4" nameend="c5"></entry>
644 <entry morerows="1" valign="top">
645 <classname>Resize_Policy</classname>
647 <entry morerows="1" valign="top">
648 <classname>hash_standard_resize_policy</classname>
651 <classname>Size_Policy</classname>
654 <classname>hash_exponential_size_policy</classname>
660 <classname>Trigger_Policy</classname>
663 <classname>hash_load_check_resize_trigger</classname> with
664 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
678 <para>And the second graphic shows the results for the native and
679 general-probe hash types. The function applied being a random
680 integer timing test using <function>find</function>.
683 <!-- results graphic 02 -->
687 <imagedata align="center" format="PDF" scale="75"
688 fileref="../images/pbds_gp_hash_int_find.pdf"/>
691 <imagedata align="center" format="PNG" scale="100"
692 fileref="../images/pbds_gp_hash_int_find.png"/>
698 The abbreviated names in the legend of the graphic above are
699 instantiated with the types in the following table.
703 <informaltable frame="all">
705 <tgroup cols="5" align="left" colsep="1" rowsep="1">
706 <colspec colname="c1"/>
707 <colspec colname="c2"/>
708 <colspec colname="c3"/>
709 <colspec colname="c4"/>
710 <colspec colname="c5"/>
713 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
714 <entry><emphasis>Parameter</emphasis></entry>
715 <entry><emphasis>Details</emphasis></entry>
716 <entry><emphasis>Parameter</emphasis></entry>
717 <entry><emphasis>Details</emphasis></entry>
725 <?dbhtml bgcolor="#B0B0B0" ?>
726 <entry namest="c1" nameend="c5">
733 <classname>std::tr1::unordered_map</classname>
736 <classname>cache_hash_code</classname>
739 <constant>false</constant>
741 <entry namest="c4" nameend="c5"></entry>
746 <?dbhtml bgcolor="#B0B0B0" ?>
747 <entry namest="c1" nameend="c5">
748 gp_hash_mod_quadp_prime_1div2_nsth_map
753 <entry morerows="3" valign="top">
754 <classname>gp_hash_table</classname>
757 <classname>Comb_Hash_Fn</classname>
760 <classname>direct_mod_range_hashing</classname>
762 <entry namest="c4" nameend="c5"></entry>
767 <classname>Probe_Fn</classname>
770 <classname>quadratic_probe_fn</classname>
772 <entry namest="c4" nameend="c5"></entry>
776 <entry morerows="1" valign="top">
777 <classname>Resize_Policy</classname>
779 <entry morerows="1" valign="top">
780 <classname>hash_standard_resize_policy</classname>
783 <classname>Size_Policy</classname>
786 <classname>hash_prime_size_policy</classname>
792 <classname>Trigger_Policy</classname>
795 <classname>hash_load_check_resize_trigger</classname> with
796 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
802 <?dbhtml bgcolor="#B0B0B0" ?>
803 <entry namest="c1" nameend="c5">
804 gp_hash_mask_linp_exp_1div2_nsth_map
809 <entry morerows="3" valign="top">
815 <classname>Comb_Hash_Fn</classname>
818 <classname>direct_mask_range_hashing</classname>
820 <entry namest="c4" nameend="c5"></entry>
825 <classname>Probe_Fn</classname>
828 <classname>linear_probe_fn</classname>
830 <entry namest="c4" nameend="c5"></entry>
834 <entry morerows="1" valign="top">
835 <classname>Resize_Policy</classname>
837 <entry morerows="1" valign="top">
838 <classname>hash_standard_resize_policy</classname>
841 <classname>Size_Policy</classname>
844 <classname>hash_exponential_size_policy</classname>
850 <classname>Trigger_Policy</classname>
853 <classname>hash_load_check_resize_trigger</classname> with
854 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
864 <section xml:id="hash.int_find.observations">
869 <para>In this setting, the choice of underlying hash-table affects
870 performance most, then the range-hashing scheme and, only finally,
871 other policies.</para>
873 <para>When comparing probing and chaining containers, it is
874 apparent that the probing containers are less efficient than the
875 collision-chaining containers (
876 <classname>std::tr1::unordered_map</classname> uses
877 collision-chaining) in this case.</para>
879 <para>Hash-Based Integer Subscript Insert Timing Test shows
880 a different case, where the situation is reversed;
883 <para>Within each type of hash-table, the range-hashing scheme
884 affects performance more than other policies; Hash-Based Text
885 <function>find</function> Find Timing Test also shows this. In the
886 above graphics should be noted that
887 <classname>std::tr1::unordered_map</classname> are hard-wired
888 currently to mod-based schemes.
895 <!-- 03 <a href="hash_int_subscript_find_test"> -->
896 <section xml:id="performance.hash.int_subscript_find">
898 Integer Subscript <function>find</function>
902 <section xml:id="hash.int_subscript_find.info">
907 <para>This test inserts a number of values with uniform
908 integer keys into a container, then performs a series of finds
909 using <function>operator[]</function>. It measures the average time
910 for <function>operator[]</function> as a function of the number of
911 values inserted.</para>
914 It uses the test file:
915 <filename>performance/ext/pb_ds/random_int_subscript_find_timing.cc</filename>
918 <para>The test checks the effect of different underlying
919 hash-tables, range-hashing functions, and trigger policies.</para>
924 <section xml:id="hash.int_subscript_find.results">
930 There are two sets of results for this type, one for
931 collision-chaining hashes, and one for general-probe hashes.
934 <para>The first graphic below shows the results for the native
935 and collision-chaining hash types, using as the function
936 applied an integer subscript timing test with
937 <function>find</function>.
940 <!-- results graphic -->
944 <imagedata align="center" format="PDF" scale="75"
945 fileref="../images/pbds_cc_hash_int_subscript_find.pdf"/>
948 <imagedata align="center" format="PNG" scale="100"
949 fileref="../images/pbds_cc_hash_int_subscript_find.png"/>
955 The abbreviated names in the legend of the graphic above are
956 instantiated with the types in the following table.
959 <informaltable frame="all">
961 <tgroup cols="5" align="left" colsep="1" rowsep="1">
962 <colspec colname="c1"/>
963 <colspec colname="c2"/>
964 <colspec colname="c3"/>
965 <colspec colname="c4"/>
966 <colspec colname="c5"/>
969 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
970 <entry><emphasis>Parameter</emphasis></entry>
971 <entry><emphasis>Details</emphasis></entry>
972 <entry><emphasis>Parameter</emphasis></entry>
973 <entry><emphasis>Details</emphasis></entry>
981 <?dbhtml bgcolor="#B0B0B0" ?>
982 <entry namest="c1" nameend="c5">
989 <classname>std::tr1::unordered_map</classname>
992 <classname>cache_hash_code</classname>
995 <constant>false</constant>
997 <entry namest="c4" nameend="c5"></entry>
1002 <?dbhtml bgcolor="#B0B0B0" ?>
1003 <entry namest="c1" nameend="c5">
1004 cc_hash_mod_prime_1div1_nsth_map
1009 <entry morerows="2" valign="top">
1010 <classname>cc_hash_table</classname>
1013 <classname>Comb_Hash_Fn</classname>
1016 <classname>direct_mod_range_hashing</classname>
1018 <entry namest="c4" nameend="c5"></entry>
1022 <entry morerows="1" valign="top">
1023 <classname>Resize_Policy</classname>
1025 <entry morerows="1" valign="top">
1026 <classname>hash_standard_resize_policy</classname>
1029 <classname>Size_Policy</classname>
1032 <classname>hash_prime_size_policy</classname>
1037 <entry valign="top">
1038 <classname>Trigger_Policy</classname>
1041 <classname>hash_load_check_resize_trigger</classname> with
1042 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
1048 <?dbhtml bgcolor="#B0B0B0" ?>
1049 <entry namest="c1" nameend="c5">
1050 cc_hash_mod_prime_1div2_nsth_map
1055 <entry morerows="2" valign="top">
1056 <classname>cc_hash_table</classname>
1059 <classname>Comb_Hash_Fn</classname>
1062 <classname>direct_mod_range_hashing</classname>
1064 <entry namest="c4" nameend="c5"></entry>
1068 <entry morerows="1" valign="top">
1069 <classname>Resize_Policy</classname>
1071 <entry morerows="1" valign="top">
1072 <classname>hash_standard_resize_policy</classname>
1075 <classname>Size_Policy</classname>
1078 <classname>hash_prime_size_policy</classname>
1083 <entry valign="top">
1084 <classname>Trigger_Policy</classname>
1087 <classname>hash_load_check_resize_trigger</classname> with
1088 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1094 <?dbhtml bgcolor="#B0B0B0" ?>
1095 <entry namest="c1" nameend="c5">
1096 cc_hash_mask_exp_1div1_nsth_map
1101 <entry morerows="2" valign="top">
1102 <classname>cc_hash_table</classname>
1105 <classname>Comb_Hash_Fn</classname>
1108 <classname>direct_mask_range_hashing</classname>
1110 <entry namest="c4" nameend="c5"></entry>
1114 <entry morerows="1" valign="top">
1115 <classname>Resize_Policy</classname>
1117 <entry morerows="1" valign="top">
1118 <classname>hash_standard_resize_policy</classname>
1121 <classname>Size_Policy</classname>
1124 <classname>hash_exponential_size_policy</classname>
1129 <entry valign="top">
1130 <classname>Trigger_Policy</classname>
1133 <classname>hash_load_check_resize_trigger</classname> with
1134 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
1140 <?dbhtml bgcolor="#B0B0B0" ?>
1141 <entry namest="c1" nameend="c5">
1142 cc_hash_mask_exp_1div2_nsth_map
1146 <entry morerows="2" valign="top">
1147 <classname>cc_hash_table</classname>
1150 <classname>Comb_Hash_Fn</classname>
1153 <classname>direct_mask_range_hashing</classname>
1155 <entry namest="c4" nameend="c5"></entry>
1159 <entry morerows="1" valign="top">
1160 <classname>Resize_Policy</classname>
1162 <entry morerows="1" valign="top">
1163 <classname>hash_standard_resize_policy</classname>
1166 <classname>Size_Policy</classname>
1169 <classname>hash_exponential_size_policy</classname>
1174 <entry valign="top">
1175 <classname>Trigger_Policy</classname>
1178 <classname>hash_load_check_resize_trigger</classname> with
1179 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1194 <para>And the second graphic shows the results for the native and
1195 general-probe hash types. The function applied being a random
1196 integer timing test using <function>find</function>.
1199 <!-- results graphic 02 -->
1203 <imagedata align="center" format="PDF" scale="75"
1204 fileref="../images/pbds_gp_hash_int_subscript_find.pdf"/>
1207 <imagedata align="center" format="PNG" scale="100"
1208 fileref="../images/pbds_gp_hash_int_subscript_find.png"/>
1214 The abbreviated names in the legend of the graphic above are
1215 instantiated with the types in the following table.
1219 <informaltable frame="all">
1221 <tgroup cols="5" align="left" colsep="1" rowsep="1">
1222 <colspec colname="c1"/>
1223 <colspec colname="c2"/>
1224 <colspec colname="c3"/>
1225 <colspec colname="c4"/>
1226 <colspec colname="c5"/>
1229 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
1230 <entry><emphasis>Parameter</emphasis></entry>
1231 <entry><emphasis>Details</emphasis></entry>
1232 <entry><emphasis>Parameter</emphasis></entry>
1233 <entry><emphasis>Details</emphasis></entry>
1241 <?dbhtml bgcolor="#B0B0B0" ?>
1242 <entry namest="c1" nameend="c5">
1249 <classname>std::tr1::unordered_map</classname>
1252 <classname>cache_hash_code</classname>
1255 <constant>false</constant>
1257 <entry namest="c4" nameend="c5"></entry>
1262 <?dbhtml bgcolor="#B0B0B0" ?>
1263 <entry namest="c1" nameend="c5">
1264 gp_hash_mod_quadp_prime_1div2_nsth_map
1269 <entry morerows="3" valign="top">
1270 <classname>gp_hash_table</classname>
1273 <classname>Comb_Hash_Fn</classname>
1276 <classname>direct_mod_range_hashing</classname>
1278 <entry namest="c4" nameend="c5"></entry>
1283 <classname>Probe_Fn</classname>
1286 <classname>quadratic_probe_fn</classname>
1288 <entry namest="c4" nameend="c5"></entry>
1292 <entry morerows="1" valign="top">
1293 <classname>Resize_Policy</classname>
1295 <entry morerows="1" valign="top">
1296 <classname>hash_standard_resize_policy</classname>
1299 <classname>Size_Policy</classname>
1302 <classname>hash_prime_size_policy</classname>
1307 <entry valign="top">
1308 <classname>Trigger_Policy</classname>
1311 <classname>hash_load_check_resize_trigger</classname> with
1312 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1318 <?dbhtml bgcolor="#B0B0B0" ?>
1319 <entry namest="c1" nameend="c5">
1320 gp_hash_mask_linp_exp_1div2_nsth_map
1325 <entry morerows="3" valign="top">
1331 <classname>Comb_Hash_Fn</classname>
1334 <classname>direct_mask_range_hashing</classname>
1336 <entry namest="c4" nameend="c5"></entry>
1341 <classname>Probe_Fn</classname>
1344 <classname>linear_probe_fn</classname>
1346 <entry namest="c4" nameend="c5"></entry>
1350 <entry morerows="1" valign="top">
1351 <classname>Resize_Policy</classname>
1353 <entry morerows="1" valign="top">
1354 <classname>hash_standard_resize_policy</classname>
1357 <classname>Size_Policy</classname>
1360 <classname>hash_exponential_size_policy</classname>
1365 <entry valign="top">
1366 <classname>Trigger_Policy</classname>
1369 <classname>hash_load_check_resize_trigger</classname> with
1370 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1381 <section xml:id="hash.int_subscript_find.observations">
1385 <para>This test shows similar results to Hash-Based
1386 Integer <classname>find</classname> Find Timing test.</para>
1392 <!-- 04 <a href="hash_random_int_subscript_insert_timing_test"> -->
1393 <section xml:id="performance.hash.int_subscript_insert">
1395 Integer Subscript <function>insert</function>
1399 <section xml:id="hash.int_subscript_insert.info">
1404 <para>This test inserts a number of values with uniform i.i.d.
1405 integer keys into a container, using
1406 <function>operator[]</function>. It measures the average time for
1407 <function>operator[]</function> as a function of the number of
1408 values inserted.</para>
1411 It uses the test file:
1412 <filename>performance/ext/pb_ds/random_int_subscript_insert_timing.cc</filename>
1415 <para>The test checks the effect of different underlying
1421 <section xml:id="hash.int_subscript_insert.results">
1427 There are two sets of results for this type, one for
1428 collision-chaining hashes, and one for general-probe hashes.
1431 <para>The first graphic below shows the results for the native
1432 and collision-chaining hash types, using as the function
1433 applied an integer subscript timing test with
1434 <function>insert</function>.
1437 <!-- results graphic -->
1441 <imagedata align="center" format="PDF" scale="75"
1442 fileref="../images/pbds_cc_hash_int_subscript_insert.pdf"/>
1445 <imagedata align="center" format="PNG" scale="100"
1446 fileref="../images/pbds_cc_hash_int_subscript_insert.png"/>
1452 The abbreviated names in the legend of the graphic above are
1453 instantiated with the types in the following table.
1456 <informaltable frame="all">
1458 <tgroup cols="5" align="left" colsep="1" rowsep="1">
1459 <colspec colname="c1"/>
1460 <colspec colname="c2"/>
1461 <colspec colname="c3"/>
1462 <colspec colname="c4"/>
1463 <colspec colname="c5"/>
1466 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
1467 <entry><emphasis>Parameter</emphasis></entry>
1468 <entry><emphasis>Details</emphasis></entry>
1469 <entry><emphasis>Parameter</emphasis></entry>
1470 <entry><emphasis>Details</emphasis></entry>
1478 <?dbhtml bgcolor="#B0B0B0" ?>
1479 <entry namest="c1" nameend="c5">
1486 <classname>std::tr1::unordered_map</classname>
1489 <classname>cache_hash_code</classname>
1492 <constant>false</constant>
1494 <entry namest="c4" nameend="c5"></entry>
1499 <?dbhtml bgcolor="#B0B0B0" ?>
1500 <entry namest="c1" nameend="c5">
1501 cc_hash_mod_prime_1div1_nsth_map
1506 <entry morerows="2" valign="top">
1507 <classname>cc_hash_table</classname>
1510 <classname>Comb_Hash_Fn</classname>
1513 <classname>direct_mod_range_hashing</classname>
1515 <entry namest="c4" nameend="c5"></entry>
1519 <entry morerows="1" valign="top">
1520 <classname>Resize_Policy</classname>
1522 <entry morerows="1" valign="top">
1523 <classname>hash_standard_resize_policy</classname>
1526 <classname>Size_Policy</classname>
1529 <classname>hash_prime_size_policy</classname>
1534 <entry valign="top">
1535 <classname>Trigger_Policy</classname>
1538 <classname>hash_load_check_resize_trigger</classname> with
1539 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
1545 <?dbhtml bgcolor="#B0B0B0" ?>
1546 <entry namest="c1" nameend="c5">
1547 cc_hash_mod_prime_1div2_nsth_map
1552 <entry morerows="2" valign="top">
1553 <classname>cc_hash_table</classname>
1556 <classname>Comb_Hash_Fn</classname>
1559 <classname>direct_mod_range_hashing</classname>
1561 <entry namest="c4" nameend="c5"></entry>
1565 <entry morerows="1" valign="top">
1566 <classname>Resize_Policy</classname>
1568 <entry morerows="1" valign="top">
1569 <classname>hash_standard_resize_policy</classname>
1572 <classname>Size_Policy</classname>
1575 <classname>hash_prime_size_policy</classname>
1580 <entry valign="top">
1581 <classname>Trigger_Policy</classname>
1584 <classname>hash_load_check_resize_trigger</classname> with
1585 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1591 <?dbhtml bgcolor="#B0B0B0" ?>
1592 <entry namest="c1" nameend="c5">
1593 cc_hash_mask_exp_1div1_nsth_map
1598 <entry morerows="2" valign="top">
1599 <classname>cc_hash_table</classname>
1602 <classname>Comb_Hash_Fn</classname>
1605 <classname>direct_mask_range_hashing</classname>
1607 <entry namest="c4" nameend="c5"></entry>
1611 <entry morerows="1" valign="top">
1612 <classname>Resize_Policy</classname>
1614 <entry morerows="1" valign="top">
1615 <classname>hash_standard_resize_policy</classname>
1618 <classname>Size_Policy</classname>
1621 <classname>hash_exponential_size_policy</classname>
1626 <entry valign="top">
1627 <classname>Trigger_Policy</classname>
1630 <classname>hash_load_check_resize_trigger</classname> with
1631 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
1637 <?dbhtml bgcolor="#B0B0B0" ?>
1638 <entry namest="c1" nameend="c5">
1639 cc_hash_mask_exp_1div2_nsth_map
1643 <entry morerows="2" valign="top">
1644 <classname>cc_hash_table</classname>
1647 <classname>Comb_Hash_Fn</classname>
1650 <classname>direct_mask_range_hashing</classname>
1652 <entry namest="c4" nameend="c5"></entry>
1656 <entry morerows="1" valign="top">
1657 <classname>Resize_Policy</classname>
1659 <entry morerows="1" valign="top">
1660 <classname>hash_standard_resize_policy</classname>
1663 <classname>Size_Policy</classname>
1666 <classname>hash_exponential_size_policy</classname>
1671 <entry valign="top">
1672 <classname>Trigger_Policy</classname>
1675 <classname>hash_load_check_resize_trigger</classname> with
1676 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1691 <para>And the second graphic shows the results for the native and
1692 general-probe hash types. The function applied being a random
1693 integer timing test using <function>find</function>.
1696 <!-- results graphic 02 -->
1700 <imagedata align="center" format="PDF" scale="75"
1701 fileref="../images/pbds_gp_hash_int_subscript_insert.pdf"/>
1704 <imagedata align="center" format="PNG" scale="100"
1705 fileref="../images/pbds_gp_hash_int_subscript_insert.png"/>
1711 The abbreviated names in the legend of the graphic above are
1712 instantiated with the types in the following table.
1716 <informaltable frame="all">
1718 <tgroup cols="5" align="left" colsep="1" rowsep="1">
1719 <colspec colname="c1"/>
1720 <colspec colname="c2"/>
1721 <colspec colname="c3"/>
1722 <colspec colname="c4"/>
1723 <colspec colname="c5"/>
1726 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
1727 <entry><emphasis>Parameter</emphasis></entry>
1728 <entry><emphasis>Details</emphasis></entry>
1729 <entry><emphasis>Parameter</emphasis></entry>
1730 <entry><emphasis>Details</emphasis></entry>
1738 <?dbhtml bgcolor="#B0B0B0" ?>
1739 <entry namest="c1" nameend="c5">
1746 <classname>std::tr1::unordered_map</classname>
1749 <classname>cache_hash_code</classname>
1752 <constant>false</constant>
1754 <entry namest="c4" nameend="c5"></entry>
1759 <?dbhtml bgcolor="#B0B0B0" ?>
1760 <entry namest="c1" nameend="c5">
1761 gp_hash_mod_quadp_prime_1div2_nsth_map
1766 <entry morerows="3" valign="top">
1767 <classname>gp_hash_table</classname>
1770 <classname>Comb_Hash_Fn</classname>
1773 <classname>direct_mod_range_hashing</classname>
1775 <entry namest="c4" nameend="c5"></entry>
1780 <classname>Probe_Fn</classname>
1783 <classname>quadratic_probe_fn</classname>
1785 <entry namest="c4" nameend="c5"></entry>
1789 <entry morerows="1" valign="top">
1790 <classname>Resize_Policy</classname>
1792 <entry morerows="1" valign="top">
1793 <classname>hash_standard_resize_policy</classname>
1796 <classname>Size_Policy</classname>
1799 <classname>hash_prime_size_policy</classname>
1804 <entry valign="top">
1805 <classname>Trigger_Policy</classname>
1808 <classname>hash_load_check_resize_trigger</classname> with
1809 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1815 <?dbhtml bgcolor="#B0B0B0" ?>
1816 <entry namest="c1" nameend="c5">
1817 gp_hash_mask_linp_exp_1div2_nsth_map
1822 <entry morerows="3" valign="top">
1828 <classname>Comb_Hash_Fn</classname>
1831 <classname>direct_mask_range_hashing</classname>
1833 <entry namest="c4" nameend="c5"></entry>
1838 <classname>Probe_Fn</classname>
1841 <classname>linear_probe_fn</classname>
1843 <entry namest="c4" nameend="c5"></entry>
1847 <entry morerows="1" valign="top">
1848 <classname>Resize_Policy</classname>
1850 <entry morerows="1" valign="top">
1851 <classname>hash_standard_resize_policy</classname>
1854 <classname>Size_Policy</classname>
1857 <classname>hash_exponential_size_policy</classname>
1862 <entry valign="top">
1863 <classname>Trigger_Policy</classname>
1866 <classname>hash_load_check_resize_trigger</classname> with
1867 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
1878 <section xml:id="hash.int_subscript_insert.observations">
1883 <para>In this setting, as in Hash-Based Text
1884 <function>find</function> Find Timing test and Hash-Based
1885 Integer <function>find</function> Find Timing test , the choice
1886 of underlying hash-table underlying hash-table affects performance
1887 most, then the range-hashing scheme, and
1888 finally any other policies.</para>
1889 <para>There are some differences, however:</para>
1891 <listitem><para>In this setting, probing tables function sometimes more
1892 efficiently than collision-chaining tables.
1893 This is explained shortly.</para></listitem>
1894 <listitem><para>The performance graphs have a "saw-tooth" shape. The
1895 average insert time rises and falls. As values are inserted
1896 into the container, the load factor grows larger. Eventually,
1897 a resize occurs. The reallocations and rehashing are
1898 relatively expensive. After this, the load factor is smaller
1899 than before.</para></listitem>
1902 <para>Collision-chaining containers use indirection for greater
1903 flexibility; probing containers store values contiguously, in
1904 an array (see Figure Motivation::Different
1905 underlying data structures A and B, respectively). It
1906 follows that for simple data types, probing containers access
1907 their allocator less frequently than collision-chaining
1908 containers, (although they still have less efficient probing
1909 sequences). This explains why some probing containers fare
1910 better than collision-chaining containers in this case.</para>
1913 Within each type of hash-table, the range-hashing scheme affects
1914 performance more than other policies. This is similar to the
1915 situation in Hash-Based Text
1916 <function>find</function> Find Timing Test and Hash-Based
1917 Integer <function>find</function> Find Timing Test.
1918 Unsurprisingly, however, containers with lower α<subscript>max</subscript> perform worse in this case,
1919 since more re-hashes are performed.</para>
1926 <!-- 05 <a href="hash_zlob_random_int_find_find_timing_test"> -->
1928 <!-- 05 <a href="hash_zlob_random_int_find_find_timing_test"> -->
1929 <section xml:id="performance.hash.zlob_int_find">
1931 Integer <function>find</function> with Skewed-Distribution
1935 <section xml:id="hash.zlob_int_find.info">
1940 <para>This test inserts a number of values with a markedly
1941 non-uniform integer keys into a container, then performs
1942 a series of finds using <function>find</function>. It measures the average
1943 time for <function>find</function> as a function of the number of values in
1944 the containers. The keys are generated as follows. First, a
1945 uniform integer is created. Then it is then shifted left 8 bits.</para>
1948 It uses the test file:
1949 <filename>performance/ext/pb_ds/hash_zlob_random_int_find_timing.cc</filename>
1952 <para>The test checks the effect of different range-hashing
1953 functions and trigger policies.</para>
1958 <section xml:id="hash.zlob_int_find.results">
1963 <para>The graphic below show the results for the native, collision-chaining, and general-probing hash types.
1966 <!-- results graphic -->
1970 <imagedata align="center" format="PDF" scale="75"
1971 fileref="../images/pbds_hash_zlob_int_find.pdf"/>
1974 <imagedata align="center" format="PNG" scale="100"
1975 fileref="../images/pbds_hash_zlob_int_find.png"/>
1981 The abbreviated names in the legend of the graphic above are
1982 instantiated with the types in the following table.
1986 <informaltable frame="all">
1988 <tgroup cols="5" align="left" colsep="1" rowsep="1">
1989 <colspec colname="c1"/>
1990 <colspec colname="c2"/>
1991 <colspec colname="c3"/>
1992 <colspec colname="c4"/>
1993 <colspec colname="c5"/>
1996 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
1997 <entry><emphasis>Parameter</emphasis></entry>
1998 <entry><emphasis>Details</emphasis></entry>
1999 <entry><emphasis>Parameter</emphasis></entry>
2000 <entry><emphasis>Details</emphasis></entry>
2008 <?dbhtml bgcolor="#B0B0B0" ?>
2009 <entry namest="c1" nameend="c5">
2016 <classname>std::tr1::unordered_map</classname>
2019 <classname>cache_hash_code</classname>
2022 <constant>false</constant>
2024 <entry namest="c4" nameend="c5"></entry>
2029 <?dbhtml bgcolor="#B0B0B0" ?>
2030 <entry namest="c1" nameend="c5">
2031 cc_hash_mod_prime_1div1_nsth_map
2036 <entry morerows="2" valign="top">
2037 <classname>cc_hash_table</classname>
2040 <classname>Comb_Hash_Fn</classname>
2043 <classname>direct_mod_range_hashing</classname>
2045 <entry namest="c4" nameend="c5"></entry>
2049 <entry morerows="1" valign="top">
2050 <classname>Resize_Policy</classname>
2052 <entry morerows="1" valign="top">
2053 <classname>hash_standard_resize_policy</classname>
2056 <classname>Size_Policy</classname>
2059 <classname>hash_prime_size_policy</classname>
2064 <entry valign="top">
2065 <classname>Trigger_Policy</classname>
2068 <classname>hash_load_check_resize_trigger</classname> with
2069 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
2075 <?dbhtml bgcolor="#B0B0B0" ?>
2076 <entry namest="c1" nameend="c5">
2077 cc_hash_mask_exp_1div1_nsth_map
2082 <entry morerows="2" valign="top">
2088 <classname>Comb_Hash_Fn</classname>
2091 <classname>direct_mask_range_hashing</classname>
2093 <entry namest="c4" nameend="c5"></entry>
2097 <entry morerows="1" valign="top">
2098 <classname>Resize_Policy</classname>
2100 <entry morerows="1" valign="top">
2101 <classname>hash_standard_resize_policy</classname>
2104 <classname>Size_Policy</classname>
2107 <classname>hash_exponential_size_policy</classname>
2112 <entry valign="top">
2113 <classname>Trigger_Policy</classname>
2116 <classname>hash_load_check_resize_trigger</classname> with
2117 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
2123 <?dbhtml bgcolor="#B0B0B0" ?>
2124 <entry namest="c1" nameend="c5">
2125 gp_hash_mod_quadp_prime_1div2_nsth_map
2130 <entry morerows="3" valign="top">
2131 <classname>gp_hash_table</classname>
2134 <classname>Comb_Hash_Fn</classname>
2137 <classname>direct_mod_range_hashing</classname>
2139 <entry namest="c4" nameend="c5"></entry>
2144 <classname>Probe_Fn</classname>
2147 <classname>quadratic_probe_fn</classname>
2149 <entry namest="c4" nameend="c5"></entry>
2153 <entry morerows="1" valign="top">
2154 <classname>Resize_Policy</classname>
2156 <entry morerows="1" valign="top">
2157 <classname>hash_standard_resize_policy</classname>
2160 <classname>Size_Policy</classname>
2163 <classname>hash_prime_size_policy</classname>
2168 <entry valign="top">
2169 <classname>Trigger_Policy</classname>
2172 <classname>hash_load_check_resize_trigger</classname> with
2173 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
2184 <section xml:id="hash.zlob_int_find.observations">
2189 <para>In this setting, the distribution of keys is so skewed that
2190 the underlying hash-table type affects performance marginally.
2191 (This is in contrast with Hash-Based Text
2192 <function>find</function> Find Timing Test, Hash-Based
2193 Integer <function>find</function> Find Timing Test, Hash-Based
2194 Integer Subscript Find Timing Test and Hash-Based
2195 Integer Subscript Insert Timing Test.)</para>
2197 <para>The range-hashing scheme affects performance dramatically. A
2198 mask-based range-hashing scheme effectively maps all values
2199 into the same bucket. Access degenerates into a search within
2200 an unordered linked-list. In the graphic above, it should be noted that
2201 <classname>std::tr1::unordered_map</classname> is hard-wired currently to mod-based and mask-based schemes,
2202 respectively.</para>
2204 <para>When observing the settings of this test, it is apparent
2205 that the keys' distribution is far from natural. One might ask
2206 if the test is not contrived to show that, in some cases,
2207 mod-based range hashing does better than mask-based range
2208 hashing. This is, in fact just the case. A
2209 more natural case in which mod-based range hashing is better was not encountered.
2210 Thus the inescapable conclusion: real-life key distributions are handled better
2211 with an appropriate hash function and a mask-based
2212 range-hashing function. (<filename>pb_ds/example/hash_shift_mask.cc</filename>
2213 shows an example of handling this a-priori known skewed
2214 distribution with a mask-based range-hashing function). If hash
2215 performance is bad, a χ<superscript>2</superscript> test can be used
2216 to check how to transform it into a more uniform
2217 distribution.</para>
2218 <para>For this reason, this library's default range-hashing
2219 function is mask-based.</para>
2226 <!-- 06 <a href="hash_random_int_erase_mem_usage_test"> -->
2228 <!-- 06 <a href="hash_random_int_erase_mem_usage_test"> -->
2229 <section xml:id="performance.hash.erase_mem">
2235 <section xml:id="hash.erase_mem.info">
2240 <para>This test inserts a number of uniform integer keys
2241 into a container, then erases all keys except one. It measures
2242 the final size of the container.</para>
2245 It uses the test file:
2246 <filename>performance/ext/pb_ds/hash_random_int_erase_mem_usage.cc</filename>
2250 <para>The test checks how containers adjust internally as their
2251 logical size decreases.</para>
2255 <section xml:id="hash.erase_mem.results">
2260 <para>The graphic below show the results for the native, collision-chaining, and general-probing hash types.
2263 <!-- results graphic -->
2267 <imagedata align="center" format="PDF" scale="75"
2268 fileref="../images/pbds_hash_int_erase_mem.pdf"/>
2271 <imagedata align="center" format="PNG" scale="100"
2272 fileref="../images/pbds_hash_int_erase_mem.png"/>
2278 The abbreviated names in the legend of the graphic above are
2279 instantiated with the types in the following table.
2283 <informaltable frame="all">
2285 <tgroup cols="5" align="left" colsep="1" rowsep="1">
2286 <colspec colname="c1"/>
2287 <colspec colname="c2"/>
2288 <colspec colname="c3"/>
2289 <colspec colname="c4"/>
2290 <colspec colname="c5"/>
2293 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
2294 <entry><emphasis>Parameter</emphasis></entry>
2295 <entry><emphasis>Details</emphasis></entry>
2296 <entry><emphasis>Parameter</emphasis></entry>
2297 <entry><emphasis>Details</emphasis></entry>
2305 <?dbhtml bgcolor="#B0B0B0" ?>
2306 <entry namest="c1" nameend="c5">
2313 <classname>std::tr1::unordered_map</classname>
2316 <classname>cache_hash_code</classname>
2319 <constant>false</constant>
2321 <entry namest="c4" nameend="c5"></entry>
2326 <?dbhtml bgcolor="#B0B0B0" ?>
2327 <entry namest="c1" nameend="c5">
2328 cc_hash_mod_prime_1div1_nsth_map
2333 <entry morerows="2" valign="top">
2334 <classname>cc_hash_table</classname>
2337 <classname>Comb_Hash_Fn</classname>
2340 <classname>direct_mod_range_hashing</classname>
2342 <entry namest="c4" nameend="c5"></entry>
2346 <entry morerows="1" valign="top">
2347 <classname>Resize_Policy</classname>
2349 <entry morerows="1" valign="top">
2350 <classname>hash_standard_resize_policy</classname>
2353 <classname>Size_Policy</classname>
2356 <classname>hash_prime_size_policy</classname>
2361 <entry valign="top">
2362 <classname>Trigger_Policy</classname>
2365 <classname>hash_load_check_resize_trigger</classname> with
2366 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1
2372 <?dbhtml bgcolor="#B0B0B0" ?>
2373 <entry namest="c1" nameend="c5">
2374 cc_hash_mask_exp_1div2_nsth_map
2379 <entry morerows="2" valign="top">
2385 <classname>Comb_Hash_Fn</classname>
2388 <classname>direct_mask_range_hashing</classname>
2390 <entry namest="c4" nameend="c5"></entry>
2394 <entry morerows="1" valign="top">
2395 <classname>Resize_Policy</classname>
2397 <entry morerows="1" valign="top">
2398 <classname>hash_standard_resize_policy</classname>
2401 <classname>Size_Policy</classname>
2404 <classname>hash_exponential_size_policy</classname>
2409 <entry valign="top">
2410 <classname>Trigger_Policy</classname>
2413 <classname>hash_load_check_resize_trigger</classname> with
2414 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
2420 <?dbhtml bgcolor="#B0B0B0" ?>
2421 <entry namest="c1" nameend="c5">
2422 gp_hash_mask_linp_exp_1div2_nsth_set
2427 <entry morerows="3" valign="top">
2428 <classname>gp_hash_table</classname>
2431 <classname>Comb_Hash_Fn</classname>
2434 <classname>direct_mask_range_hashing</classname>
2436 <entry namest="c4" nameend="c5"></entry>
2441 <classname>Probe_Fn</classname>
2444 <classname>linear_probe_fn</classname>
2446 <entry namest="c4" nameend="c5"></entry>
2450 <entry morerows="1" valign="top">
2451 <classname>Resize_Policy</classname>
2453 <entry morerows="1" valign="top">
2454 <classname>hash_standard_resize_policy</classname>
2457 <classname>Size_Policy</classname>
2460 <classname>hash_exponential_size_policy</classname>
2465 <entry valign="top">
2466 <classname>Trigger_Policy</classname>
2469 <classname>hash_load_check_resize_trigger</classname> with
2470 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
2481 <section xml:id="hash.erase_mem.observations">
2485 <para>The standard's hash-based containers act very differently than trees in
2486 this respect. When erasing numerous keys from an standard
2487 associative-container, the resulting memory user varies greatly
2488 depending on whether the container is tree-based or hash-based.
2489 This is a fundamental consequence of the standard's interface for
2490 associative containers, and it is not due to a specific
2491 implementation.</para>
2498 <section xml:id="performance.branch">
2499 <info><title>Branch-Based</title></info>
2502 <!-- 01 <a href="tree_text_insert_timing_test"> -->
2503 <section xml:id="performance.branch.text_insert">
2505 Text <function>insert</function>
2509 <section xml:id="branch.text_insert.info">
2515 <para>This test inserts a number of values with keys from an arbitrary
2516 text ([wickland96thirty]) into a container
2517 using <function>insert</function> . It measures the average time
2518 for <function>insert</function> as a function of the number of
2519 values inserted.</para>
2521 <para>The test checks the effect of different underlying
2522 data structures.</para>
2525 It uses the test file:
2526 <filename>performance/ext/pb_ds/tree_text_insert_timing.cc</filename>
2532 <section xml:id="branch.text_insert.results">
2537 <para>The three graphics below show the results for the native
2538 tree and this library's node-based trees, the native tree and
2539 this library's vector-based trees, and the native tree
2540 and this library's PATRICIA-trie, respectively.
2543 <para>The graphic immediately below shows the results for the
2544 native tree type and several node-based tree types.
2547 <!-- results graphic -->
2551 <imagedata align="center" format="PDF" scale="75"
2552 fileref="../images/pbds_tree_text_insert_node.pdf"/>
2555 <imagedata align="center" format="PNG" scale="100"
2556 fileref="../images/pbds_tree_text_insert_node.png"/>
2562 The abbreviated names in the legend of the graphic above are
2563 instantiated with the types in the following table.
2567 <informaltable frame="all">
2568 <tgroup cols="3" align="left" colsep="1" rowsep="1">
2569 <colspec colname="c1"/>
2570 <colspec colname="c2"/>
2571 <colspec colname="c3"/>
2574 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
2575 <entry><emphasis>Parameter</emphasis></entry>
2576 <entry><emphasis>Details</emphasis></entry>
2584 <?dbhtml bgcolor="#B0B0B0" ?>
2585 <entry namest="c1" nameend="c3">
2592 <classname>std::map</classname>
2594 <entry namest="c2" nameend="c3"></entry>
2599 <?dbhtml bgcolor="#B0B0B0" ?>
2600 <entry namest="c1" nameend="c3">
2606 <entry morerows="1" valign="top">
2607 <classname>tree</classname>
2610 <classname>Tag</classname>
2613 <classname>splay_tree_tag</classname>
2619 <classname>Node_update</classname>
2622 <classname>null_node_update</classname>
2629 <?dbhtml bgcolor="#B0B0B0" ?>
2630 <entry namest="c1" nameend="c3">
2636 <entry morerows="1" valign="top">
2637 <classname>tree</classname>
2640 <classname>Tag</classname>
2643 <classname>rb_tree_tag</classname>
2649 <classname>Node_update</classname>
2652 <classname>null_node_update</classname>
2662 <para>The graphic below shows the results for the
2663 native tree type and a vector-based tree type.
2666 <!-- results graphic -->
2670 <imagedata align="center" format="PDF" scale="75"
2671 fileref="../images/pbds_tree_text_insert_vector.pdf"/>
2674 <imagedata align="center" format="PNG" scale="100"
2675 fileref="../images/pbds_tree_text_insert_vector.png"/>
2681 The abbreviated names in the legend of the graphic above are
2682 instantiated with the types in the following table.
2686 <informaltable frame="all">
2688 <tgroup cols="3" align="left" colsep="1" rowsep="1">
2689 <colspec colname="c1"/>
2690 <colspec colname="c2"/>
2691 <colspec colname="c3"/>
2694 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
2695 <entry><emphasis>Parameter</emphasis></entry>
2696 <entry><emphasis>Details</emphasis></entry>
2704 <?dbhtml bgcolor="#B0B0B0" ?>
2705 <entry namest="c1" nameend="c3">
2712 <classname>std::map</classname>
2714 <entry namest="c2" nameend="c3"></entry>
2719 <?dbhtml bgcolor="#B0B0B0" ?>
2720 <entry namest="c1" nameend="c3">
2726 <entry morerows="1" valign="top">
2727 <classname>tree</classname>
2730 <classname>Tag</classname>
2733 <classname>ov_tree_tag</classname>
2739 <classname>Node_update</classname>
2742 <classname>null_node_update</classname>
2754 <para>The graphic below shows the results for the
2755 native tree type and a PATRICIA trie type.
2758 <!-- results graphic -->
2762 <imagedata align="center" format="PDF" scale="75"
2763 fileref="../images/pbds_tree_text_insert_trie.pdf"/>
2766 <imagedata align="center" format="PNG" scale="100"
2767 fileref="../images/pbds_tree_text_insert_trie.png"/>
2773 The abbreviated names in the legend of the graphic above are
2774 instantiated with the types in the following table.
2778 <informaltable frame="all">
2780 <tgroup cols="3" align="left" colsep="1" rowsep="1">
2781 <colspec colname="c1"/>
2782 <colspec colname="c2"/>
2783 <colspec colname="c3"/>
2786 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
2787 <entry><emphasis>Parameter</emphasis></entry>
2788 <entry><emphasis>Details</emphasis></entry>
2796 <?dbhtml bgcolor="#B0B0B0" ?>
2797 <entry namest="c1" nameend="c3">
2804 <classname>std::map</classname>
2806 <entry namest="c2" nameend="c3"></entry>
2811 <?dbhtml bgcolor="#B0B0B0" ?>
2812 <entry namest="c1" nameend="c3">
2818 <entry morerows="1" valign="top">
2819 <classname>tree</classname>
2822 <classname>Tag</classname>
2825 <classname>pat_trie_tag</classname>
2831 <classname>Node_update</classname>
2834 <classname>null_node_update</classname>
2845 <section xml:id="branch.text_insert.observations">
2850 <para>Observing the first graphic implies that for this setting, a splay tree
2851 (<classname>tree</classname> with <classname>Tag
2852 </classname> = <classname>splay_tree_tag</classname>) does not do
2853 well. See also the Branch-Based
2854 Text <function>find</function> Find Timing Test. The two
2855 red-black trees perform better.</para>
2857 <para>Observing the second graphic, an ordered-vector tree
2858 (<classname>tree</classname> with <classname>Tag
2859 </classname> = <classname>ov_tree_tag</classname>) performs
2860 abysmally. Inserting into this type of tree has linear complexity
2861 [ austern00noset].</para>
2863 <para>Observing the third and last graphic, A PATRICIA trie
2864 (<classname>trie</classname> with <classname>Tag
2865 </classname> = <classname>pat_trie_tag</classname>) has abysmal
2866 performance, as well. This is not that surprising, since a
2867 large-fan-out PATRICIA trie works like a hash table with
2868 collisions resolved by a sub-trie. Each time a collision is
2869 encountered, a new "hash-table" is built A large fan-out PATRICIA
2870 trie, however, doe does well in look-ups (see Branch-Based
2871 Text <function>find</function> Find Timing Test). It may be
2872 beneficial in semi-static settings.</para>
2878 <!-- 02 <a href="tree_text_find_find_timing_test"> -->
2879 <section xml:id="performance.branch.text_find">
2881 Text <function>find</function>
2885 <section xml:id="branch.text_find.info">
2891 <para>This test inserts a number of values with keys from an
2892 arbitrary text ([wickland96thirty]) into
2893 a container, then performs a series of finds using
2894 <function>find</function>. It measures the average time
2895 for <function>find</function> as a function of the number of
2896 values inserted.</para>
2899 It uses the test file:
2900 <filename>performance/ext/pb_ds/text_find_timing.cc</filename>
2904 <para>The test checks the effect of different underlying
2905 data structures.</para>
2909 <section xml:id="branch.text_find.results">
2914 <para>The graphic immediately below shows the results for the
2915 native tree type and several other tree types.
2918 <!-- results graphic -->
2922 <imagedata align="center" format="PDF" scale="75"
2923 fileref="../images/pbds_tree_text_find.pdf"/>
2926 <imagedata align="center" format="PNG" scale="100"
2927 fileref="../images/pbds_tree_text_find.png"/>
2933 The abbreviated names in the legend of the graphic above are
2934 instantiated with the types in the following table.
2938 <informaltable frame="all">
2940 <tgroup cols="3" align="left" colsep="1" rowsep="1">
2941 <colspec colname="c1"/>
2942 <colspec colname="c2"/>
2943 <colspec colname="c3"/>
2946 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
2947 <entry><emphasis>Parameter</emphasis></entry>
2948 <entry><emphasis>Details</emphasis></entry>
2956 <?dbhtml bgcolor="#B0B0B0" ?>
2957 <entry namest="c1" nameend="c3">
2964 <classname>std::map</classname>
2966 <entry namest="c2" nameend="c3"></entry>
2971 <?dbhtml bgcolor="#B0B0B0" ?>
2972 <entry namest="c1" nameend="c3">
2978 <entry morerows="1" valign="top">
2979 <classname>tree</classname>
2982 <classname>Tag</classname>
2985 <classname>splay_tree_tag</classname>
2991 <classname>Node_Update</classname>
2994 <classname>null_node_update</classname>
3001 <?dbhtml bgcolor="#B0B0B0" ?>
3002 <entry namest="c1" nameend="c3">
3008 <entry morerows="1" valign="top">
3009 <classname>tree</classname>
3012 <classname>Tag</classname>
3015 <classname>rb_tree_tag</classname>
3021 <classname>Node_Update</classname>
3024 <classname>null_node_update</classname>
3031 <?dbhtml bgcolor="#B0B0B0" ?>
3032 <entry namest="c1" nameend="c3">
3038 <entry morerows="1" valign="top">
3039 <classname>tree</classname>
3042 <classname>Tag</classname>
3045 <classname>ov_tree_tag</classname>
3051 <classname>Node_Update</classname>
3054 <classname>null_node_update</classname>
3061 <?dbhtml bgcolor="#B0B0B0" ?>
3062 <entry namest="c1" nameend="c3">
3068 <entry morerows="1" valign="top">
3069 <classname>tree</classname>
3072 <classname>Tag</classname>
3075 <classname>pat_trie_tag</classname>
3081 <classname>Node_Update</classname>
3084 <classname>null_node_update</classname>
3094 <section xml:id="branch.text_find.observations">
3099 <para>For this setting, a splay tree (<classname>tree</classname>
3101 </classname> = <classname>splay_tree_tag</classname>) does not do
3102 well. This is possibly due to two reasons:</para>
3105 <listitem><para>A splay tree is not guaranteed to be balanced [motwani95random]. If a
3106 splay tree contains n nodes, its average root-leaf
3107 path can be m >> log(n).</para></listitem>
3108 <listitem><para>Assume a specific root-leaf search path has length
3109 m, and the search-target node has distance m'
3110 from the root. A red-black tree will require m + 1
3111 comparisons to find the required node; a splay tree will
3112 require 2 m' comparisons. A splay tree, consequently,
3113 can perform many more comparisons than a red-black tree.</para></listitem>
3115 <para>An ordered-vector tree (<classname>tree</classname>
3116 with <classname>Tag</classname> = <classname>ov_tree_tag</classname>), a red-black
3117 tree (<classname>tree</classname>
3118 with <classname>Tag</classname> = <classname>rb_tree_tag</classname>), and the
3119 native red-black tree all share approximately the same
3121 <para>An ordered-vector tree is slightly slower than red-black
3122 trees, since it requires, in order to find a key, more math
3123 operations than they do. Conversely, an ordered-vector tree
3124 requires far lower space than the others. ([austern00noset], however,
3125 seems to have an implementation that is also faster than a
3126 red-black tree).</para>
3127 <para>A PATRICIA trie (<classname>trie</classname>
3128 with <classname>Tag</classname> = <classname>pat_trie_tag</classname>) has good
3129 look-up performance, due to its large fan-out in this case. In
3130 this setting, a PATRICIA trie has look-up performance comparable
3131 to a hash table (see Hash-Based Text
3132 <classname>find</classname> Timing Test), but it is order
3133 preserving. This is not that surprising, since a large-fan-out
3134 PATRICIA trie works like a hash table with collisions resolved
3135 by a sub-trie. A large-fan-out PATRICIA trie does not do well on
3136 modifications (see Tree-Based and Trie-Based
3137 Text Insert Timing Test). Therefore, it is possibly beneficial in
3138 semi-static settings.</para>
3143 <!-- 03 <a href="tree_text_lor_find_find_timing_test"> -->
3144 <section xml:id="performance.branch.text_lor_find">
3147 Text <function>find</function> with Locality-of-Reference
3151 <section xml:id="branch.text_lor_find.info">
3158 <para>This test inserts a number of values with keys from an
3159 arbitrary text ([wickland96thirty]) into
3160 a container, then performs a series of finds using
3161 <function>find</function>. It is different than Tree-Based and
3162 Trie-Based Text <function>find</function> Find Timing Test in the
3163 sequence of finds it performs: this test performs multiple
3164 <function>find</function>s on the same key before moving on to the next
3165 key. It measures the average time for <function>find</function> as a
3166 function of the number of values inserted.</para>
3170 It uses the test file:
3171 <filename>performance/ext/pb_ds/tree_text_lor_find_timing.cc</filename>
3174 <para>The test checks the effect of different underlying
3175 data structures in a locality-of-reference setting.</para>
3179 <section xml:id="branch.text_lor_find.results">
3184 <para>The graphic immediately below shows the results for the
3185 native tree type and several other tree types.
3188 <!-- results graphic -->
3192 <imagedata align="center" format="PDF" scale="75"
3193 fileref="../images/pbds_tree_text_lor_find.pdf"/>
3196 <imagedata align="center" format="PNG" scale="100"
3197 fileref="../images/pbds_tree_text_lor_find.png"/>
3203 The abbreviated names in the legend of the graphic above are
3204 instantiated with the types in the following table.
3208 <informaltable frame="all">
3210 <tgroup cols="3" align="left" colsep="1" rowsep="1">
3211 <colspec colname="c1"/>
3212 <colspec colname="c2"/>
3213 <colspec colname="c3"/>
3216 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
3217 <entry><emphasis>Parameter</emphasis></entry>
3218 <entry><emphasis>Details</emphasis></entry>
3226 <?dbhtml bgcolor="#B0B0B0" ?>
3227 <entry namest="c1" nameend="c3">
3234 <classname>std::map</classname>
3236 <entry namest="c2" nameend="c3"></entry>
3241 <?dbhtml bgcolor="#B0B0B0" ?>
3242 <entry namest="c1" nameend="c3">
3248 <entry morerows="1" valign="top">
3249 <classname>tree</classname>
3252 <classname>Tag</classname>
3255 <classname>splay_tree_tag</classname>
3261 <classname>Node_Update</classname>
3264 <classname>null_node_update</classname>
3271 <?dbhtml bgcolor="#B0B0B0" ?>
3272 <entry namest="c1" nameend="c3">
3278 <entry morerows="1" valign="top">
3279 <classname>tree</classname>
3282 <classname>Tag</classname>
3285 <classname>rb_tree_tag</classname>
3291 <classname>Node_Update</classname>
3294 <classname>null_node_update</classname>
3301 <?dbhtml bgcolor="#B0B0B0" ?>
3302 <entry namest="c1" nameend="c3">
3308 <entry morerows="1" valign="top">
3309 <classname>tree</classname>
3312 <classname>Tag</classname>
3315 <classname>ov_tree_tag</classname>
3321 <classname>Node_Update</classname>
3324 <classname>null_node_update</classname>
3331 <?dbhtml bgcolor="#B0B0B0" ?>
3332 <entry namest="c1" nameend="c3">
3338 <entry morerows="1" valign="top">
3339 <classname>tree</classname>
3342 <classname>Tag</classname>
3345 <classname>pat_trie_tag</classname>
3351 <classname>Node_Update</classname>
3354 <classname>null_node_update</classname>
3364 <section xml:id="branch.text_lor_find.observations">
3369 <para>For this setting, an ordered-vector tree
3370 (<classname>tree</classname> with <classname>Tag</classname>
3371 = <classname>ov_tree_tag</classname>), a red-black tree
3372 (<classname>tree</classname> with <classname>Tag</classname>
3373 = <classname>rb_tree_tag</classname>), and the native red-black
3374 tree all share approximately the same performance.</para>
3375 <para>A splay tree (<classname>tree</classname>
3376 with <classname>Tag</classname> = <classname>splay_tree_tag</classname>) does
3377 much better, since each (successful) find "bubbles" the
3378 corresponding node to the root of the tree.</para>
3383 <!-- 04 <a href="tree_split_join_timing_test"> -->
3384 <section xml:id="performance.branch.split_join">
3387 <function>split</function> and <function>join</function>
3391 <section xml:id="branch.split_join.info">
3397 <para>This test a container, inserts into a number of values, splits
3398 the container at the median, and joins the two containers. (If the
3399 containers are one of this library's trees,
3400 it splits and joins with the <function>split</function> and
3401 <function>join</function> method; otherwise, it uses the <function>erase</function> and
3402 <function>insert</function> methods.) It measures the time for splitting
3403 and joining the containers as a function of the number of
3404 values inserted.</para>
3407 It uses the test file:
3408 <filename>performance/ext/pb_ds/tree_split_join_timing.cc</filename>
3412 <para>The test checks the performance difference of <function>join</function>
3413 as opposed to a sequence of <function>insert</function> operations; by
3414 implication, this test checks the most efficient way to erase a
3415 sub-sequence from a tree-like-based container, since this can
3416 always be performed by a small sequence of splits and joins.
3420 <section xml:id="branch.split_join.results">
3425 <para>The graphic immediately below shows the results for the
3426 native tree type and several other tree types.
3429 <!-- results graphic -->
3433 <imagedata align="center" format="PDF" scale="75"
3434 fileref="../images/pbds_tree_split_join.pdf"/>
3437 <imagedata align="center" format="PNG" scale="100"
3438 fileref="../images/pbds_tree_split_join.png"/>
3444 The abbreviated names in the legend of the graphic above are
3445 instantiated with the types in the following table.
3449 <informaltable frame="all">
3451 <tgroup cols="3" align="left" colsep="1" rowsep="1">
3452 <colspec colname="c1"/>
3453 <colspec colname="c2"/>
3454 <colspec colname="c3"/>
3457 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
3458 <entry><emphasis>Parameter</emphasis></entry>
3459 <entry><emphasis>Details</emphasis></entry>
3467 <?dbhtml bgcolor="#B0B0B0" ?>
3468 <entry namest="c1" nameend="c3">
3475 <classname>std::set</classname>
3477 <entry namest="c2" nameend="c3"></entry>
3482 <?dbhtml bgcolor="#B0B0B0" ?>
3483 <entry namest="c1" nameend="c3">
3489 <entry morerows="1" valign="top">
3490 <classname>tree</classname>
3493 <classname>Tag</classname>
3496 <classname>splay_tree_tag</classname>
3502 <classname>Node_Update</classname>
3505 <classname>null_node_update</classname>
3512 <?dbhtml bgcolor="#B0B0B0" ?>
3513 <entry namest="c1" nameend="c3">
3519 <entry morerows="1" valign="top">
3520 <classname>tree</classname>
3523 <classname>Tag</classname>
3526 <classname>rb_tree_tag</classname>
3532 <classname>Node_Update</classname>
3535 <classname>null_node_update</classname>
3542 <?dbhtml bgcolor="#B0B0B0" ?>
3543 <entry namest="c1" nameend="c3">
3549 <entry morerows="1" valign="top">
3550 <classname>tree</classname>
3553 <classname>Tag</classname>
3556 <classname>ov_tree_tag</classname>
3562 <classname>Node_Update</classname>
3565 <classname>null_node_update</classname>
3572 <?dbhtml bgcolor="#B0B0B0" ?>
3573 <entry namest="c1" nameend="c3">
3579 <entry morerows="1" valign="top">
3580 <classname>tree</classname>
3583 <classname>Tag</classname>
3586 <classname>pat_trie_tag</classname>
3592 <classname>Node_Update</classname>
3595 <classname>null_node_update</classname>
3605 <section xml:id="branch.split_join.observations">
3610 <para>In this test, the native red-black trees must be split and
3611 joined externally, through a sequence of <function>erase</function> and
3612 <function>insert</function> operations. This is clearly
3613 super-linear, and it is not that surprising that the cost is
3615 <para>This library's tree-based containers use in this test the
3616 <function>split</function> and <function>join</function> methods,
3617 which have lower complexity: the <function>join</function> method
3618 of a splay tree (<classname>tree</classname>
3619 with <classname>Tag </classname>
3620 = <classname>splay_tree_tag</classname>) is quadratic in the
3621 length of the longest root-leaf path, and linear in the total
3622 number of elements; the <function>join</function> method of a
3623 red-black tree (<classname>tree</classname>
3624 with <classname>Tag </classname>
3625 = <classname>rb_tree_tag</classname>) or an ordered-vector tree
3626 (<classname>tree</classname> with <classname>Tag </classname>
3627 = <classname>ov_tree_tag</classname>) is linear in the number of
3630 <para>Asides from orders of growth, this library's trees access their
3631 allocator very little in these operations, and some of them do not
3632 access it at all. This leads to lower constants in their
3633 complexity, and, for some containers, to exception-free splits and
3634 joins (which can be determined
3635 via <classname>container_traits</classname>).</para>
3637 <para>It is important to note that <function>split</function> and
3638 <function>join</function> are not esoteric methods - they are the most
3639 efficient means of erasing a contiguous range of values from a
3640 tree based container.</para>
3644 <!-- 05 <a href="tree_order_statistics_timing_test"> -->
3645 <section xml:id="performance.branch.order_statistics">
3652 <section xml:id="branch.order_statistics.info">
3657 <para>This test creates a container, inserts random integers into the
3658 the container, and then checks the order-statistics of the
3659 container's values. (If the container is one of this
3660 library's trees, it does this with
3661 the <function>order_of_key</function> method of
3662 <classname>tree_order_statistics_node_update</classname>
3663 ; otherwise, it uses the <function>find</function> method and
3664 <function>std::distance</function>.) It measures the average
3665 time for such queries as a function of the number of values
3669 It uses the test file:
3670 <filename>performance/ext/pb_ds/tree_order_statistics_timing.cc</filename>
3673 <para>The test checks the performance difference of policies based
3674 on node-invariant as opposed to a external functions.</para>
3678 <section xml:id="branch.order_statistics.results">
3683 <para>The graphic immediately below shows the results for the
3684 native tree type and several other tree types.
3687 <!-- results graphic -->
3691 <imagedata align="center" format="PDF" scale="75"
3692 fileref="../images/pbds_tree_order_statistics.pdf"/>
3695 <imagedata align="center" format="PNG" scale="100"
3696 fileref="../images/pbds_tree_order_statistics.png"/>
3702 The abbreviated names in the legend of the graphic above are
3703 instantiated with the types in the following table.
3707 <informaltable frame="all">
3709 <tgroup cols="3" align="left" colsep="1" rowsep="1">
3710 <colspec colname="c1"/>
3711 <colspec colname="c2"/>
3712 <colspec colname="c3"/>
3715 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
3716 <entry><emphasis>Parameter</emphasis></entry>
3717 <entry><emphasis>Details</emphasis></entry>
3725 <?dbhtml bgcolor="#B0B0B0" ?>
3726 <entry namest="c1" nameend="c3">
3733 <classname>std::set</classname>
3735 <entry namest="c2" nameend="c3"></entry>
3740 <?dbhtml bgcolor="#B0B0B0" ?>
3741 <entry namest="c1" nameend="c3">
3747 <entry morerows="1" valign="top">
3748 <classname>tree</classname>
3751 <classname>Tag</classname>
3754 <classname>splay_tree_tag</classname>
3760 <classname>Node_Update</classname>
3763 <classname>tree_order_statistics_node_update</classname>
3770 <?dbhtml bgcolor="#B0B0B0" ?>
3771 <entry namest="c1" nameend="c3">
3777 <entry morerows="1" valign="top">
3778 <classname>tree</classname>
3781 <classname>Tag</classname>
3784 <classname>rb_tree_tag</classname>
3790 <classname>Node_Update</classname>
3793 <classname>tree_order_statistics_node_update</classname>
3804 <section xml:id="branch.order_statistics.observations">
3808 <para>In this test, the native red-black tree can support
3809 order-statistics queries only externally, by performing a
3810 <classname>find</classname> (alternatively, <classname>lower_bound</classname> or
3811 <classname>upper_bound</classname> ) and then using <classname>std::distance</classname> .
3812 This is clearly linear, and it is not that surprising that the
3813 cost is high.</para>
3814 <para>This library's tree-based containers use in this test the
3815 <classname>order_of_key</classname> method of <classname>tree_order_statistics_node_update</classname>.
3816 This method has only linear complexity in the length of the
3817 root-node path. Unfortunately, the average path of a splay tree
3818 (<classname>tree</classname>
3819 with <classname>Tag =</classname> <classname>splay_tree_tag</classname> ) can
3820 be higher than logarithmic; the longest path of a red-black
3821 tree (<classname>tree</classname>
3822 with <classname>Tag =</classname> <classname>rb_tree_tag</classname> ) is
3823 logarithmic in the number of elements. Consequently, the splay
3824 tree has worse performance than the red-black tree.</para>
3828 </section> <!-- branch -->
3830 <section xml:id="performance.multimap">
3831 <info><title>Multimap</title></info>
3835 <!-- 01 <a href="multimap_text_find_timing_test_small"> -->
3836 <section xml:id="performance.multimap.text_find_small">
3838 Text <function>find</function> with Small Secondary-to-Primary Key Ratios
3842 <section xml:id="multimap.text_find_small.info">
3847 <para>This test inserts a number of pairs into a container. The
3848 first item of each pair is a string from an arbitrary text
3849 ([wickland96thirty]), and
3850 the second is a uniform i.i.d.integer. The container is a
3851 "multimap" - it considers the first member of each pair as a
3852 primary key, and the second member of each pair as a secondary
3853 key (see Motivation::Associative
3854 Containers::Alternative to Multiple Equivalent Keys). There
3855 are 400 distinct primary keys, and the ratio of secondary keys
3856 to primary keys ranges from 1 to 5.</para>
3857 <para>The test measures the average find-time as a function of the
3858 number of values inserted. For this library's containers, it
3859 finds the secondary key from a container obtained from finding
3860 a primary key. For the native multimaps, it searches a range
3861 obtained using <classname>std::equal_range</classname> on a primary key.</para>
3864 It uses the test file:
3865 <filename>performance/ext/pb_ds/multimap_text_find_timing_small.cc</filename>
3868 <para>The test checks the find-time scalability of different
3869 "multimap" designs.</para>
3873 <section xml:id="multimap.text_find_small.results">
3878 <para>The graphic below show the results for "multimaps" which
3879 use a tree-based container for primary keys.
3882 <!-- results graphic -->
3886 <imagedata align="center" format="PNG" scale="100"
3887 fileref="../images/pbds_multimap_text_find_small_s2p_tree.png"/>
3890 <imagedata align="center" format="PDF" scale="33"
3891 fileref="../images/pbds_multimap_text_find_small_s2p_tree.pdf"/>
3897 The abbreviated names in the legend of the graphic above are
3898 instantiated with the types in the following table.
3902 <informaltable frame="all">
3904 <tgroup cols="7" align="left" colsep="1" rowsep="1">
3905 <colspec colname="c1"/>
3906 <colspec colname="c2"/>
3907 <colspec colname="c3"/>
3908 <colspec colname="c4"/>
3909 <colspec colname="c5"/>
3910 <colspec colname="c6"/>
3911 <colspec colname="c7"/>
3914 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
3915 <entry><emphasis>Parameter</emphasis></entry>
3916 <entry><emphasis>Details</emphasis></entry>
3917 <entry><emphasis>Parameter</emphasis></entry>
3918 <entry><emphasis>Details</emphasis></entry>
3919 <entry><emphasis>Parameter</emphasis></entry>
3920 <entry><emphasis>Details</emphasis></entry>
3928 <?dbhtml bgcolor="#B0B0B0" ?>
3929 <entry namest="c1" nameend="c7">
3936 <classname>std::multimap</classname>
3938 <entry namest="c2" nameend="c7"></entry>
3941 <!-- multimap 01 -->
3943 <?dbhtml bgcolor="#B0B0B0" ?>
3944 <entry namest="c1" nameend="c7">
3945 rb_tree_mmap_lu_mtf_set
3950 <entry morerows="2" valign="top">
3951 <classname>tree</classname>
3954 <classname>Tag</classname>
3957 <classname>rb_tree_tag</classname>
3959 <entry namest="c4" nameend="c7"></entry>
3964 <classname>Node_Update</classname>
3967 <classname>null_node_update</classname>
3969 <entry namest="c4" nameend="c7"></entry>
3973 <classname>Mapped</classname>
3976 <classname>list_update</classname>
3979 <classname>Update_Policy</classname>
3982 <classname>lu_move_to_front_policy</classname>
3984 <entry namest="c6" nameend="c7"></entry>
3987 <!-- multimap 02 -->
3989 <?dbhtml bgcolor="#B0B0B0" ?>
3990 <entry namest="c1" nameend="c7">
3991 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
3996 <entry morerows="4" valign="top">
3997 <classname>tree</classname>
4000 <classname>Tag</classname>
4003 <classname>rb_tree_tag</classname>
4005 <entry namest="c4" nameend="c7"></entry>
4010 <classname>Node_Update</classname>
4013 <classname>null_node_update</classname>
4015 <entry namest="c4" nameend="c7"></entry>
4019 <entry morerows="2" valign="top">
4020 <classname>Mapped</classname>
4022 <entry morerows="2" valign="top">
4023 <classname>cc_hash_table</classname>
4026 <classname>Comb_Hash_Fn</classname>
4029 <classname>direct_mask_range_hashing</classname>
4031 <entry namest="c6" nameend="c7"></entry>
4035 <entry morerows="1" valign="top">
4036 <classname>Resize_Policy</classname>
4038 <entry morerows="1" valign="top">
4039 <classname>hash_standard_resize_policy</classname>
4042 <classname>Size_Policy</classname>
4045 <classname>hash_exponential_size_policy</classname>
4050 <entry valign="top">
4051 <classname>Trigger_Policy</classname>
4054 <classname>hash_load_check_resize_trigger</classname> with
4055 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4064 <para>The graphic below show the results for "multimaps" which
4065 use a hash-based container for primary keys.
4068 <!-- results graphic -->
4072 <imagedata align="center" format="PNG" scale="100"
4073 fileref="../images/pbds_multimap_text_find_small_s2p_hash.png"/>
4076 <imagedata align="center" format="PDF" scale="33"
4077 fileref="../images/pbds_multimap_text_find_small_s2p_hash.pdf"/>
4083 The abbreviated names in the legend of the graphic above are
4084 instantiated with the types in the following table.
4087 <informaltable frame="all">
4089 <tgroup cols="7" align="left" colsep="1" rowsep="1">
4090 <colspec colname="c1"/>
4091 <colspec colname="c2"/>
4092 <colspec colname="c3"/>
4093 <colspec colname="c4"/>
4094 <colspec colname="c5"/>
4095 <colspec colname="c6"/>
4096 <colspec colname="c7"/>
4099 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
4100 <entry><emphasis>Parameter</emphasis></entry>
4101 <entry><emphasis>Details</emphasis></entry>
4102 <entry><emphasis>Parameter</emphasis></entry>
4103 <entry><emphasis>Details</emphasis></entry>
4104 <entry><emphasis>Parameter</emphasis></entry>
4105 <entry><emphasis>Details</emphasis></entry>
4113 <?dbhtml bgcolor="#B0B0B0" ?>
4114 <entry namest="c1" nameend="c7">
4121 <classname>std::tr1::unordered_multimap</classname>
4123 <entry namest="c2" nameend="c7"></entry>
4126 <!-- multimap 01 -->
4128 <?dbhtml bgcolor="#B0B0B0" ?>
4129 <entry namest="c1" nameend="c7">
4130 rb_tree_mmap_lu_mtf_set
4135 <entry morerows="3" valign="top">
4141 <classname>Comb_Hash_Fn</classname>
4144 <classname>direct_mask_range_hashing</classname>
4146 <entry namest="c4" nameend="c7"></entry>
4149 <entry morerows="1" valign="top">
4150 <classname>Resize_Policy</classname>
4152 <entry morerows="1" valign="top">
4153 <classname>hash_standard_resize_policy</classname>
4156 <classname>Size_Policy</classname>
4159 <classname>hash_exponential_size_policy</classname>
4161 <entry namest="c6" nameend="c7"></entry>
4165 <entry valign="top">
4166 <classname>Trigger_Policy</classname>
4169 <classname>hash_load_check_resize_trigger</classname> with
4170 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4172 <entry namest="c6" nameend="c7"></entry>
4177 <classname>Mapped</classname>
4180 <classname>list_update</classname>
4183 <classname>Update_Policy</classname>
4186 <classname>lu_move_to_front_policy</classname>
4188 <entry namest="c6" nameend="c7"></entry>
4191 <!-- multimap 02 -->
4193 <?dbhtml bgcolor="#B0B0B0" ?>
4194 <entry namest="c1" nameend="c7">
4195 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
4200 <entry morerows="5" valign="top">
4206 <classname>Comb_Hash_Fn</classname>
4209 <classname>direct_mask_range_hashing</classname>
4211 <entry namest="c4" nameend="c7"></entry>
4214 <entry morerows="1" valign="top">
4215 <classname>Resize_Policy</classname>
4217 <entry morerows="1" valign="top">
4218 <classname>hash_standard_resize_policy</classname>
4221 <classname>Size_Policy</classname>
4224 <classname>hash_exponential_size_policy</classname>
4226 <entry namest="c6" nameend="c7"></entry>
4230 <entry valign="top">
4231 <classname>Trigger_Policy</classname>
4234 <classname>hash_load_check_resize_trigger</classname> with
4235 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4237 <entry namest="c6" nameend="c7"></entry>
4241 <entry morerows="2" valign="top">
4242 <classname>Mapped</classname>
4244 <entry morerows="2" valign="top">
4245 <classname>cc_hash_table</classname>
4248 <classname>Comb_Hash_Fn</classname>
4251 <classname>direct_mask_range_hashing</classname>
4253 <entry namest="c6" nameend="c7"></entry>
4257 <entry morerows="1" valign="top">
4258 <classname>Resize_Policy</classname>
4260 <entry morerows="1" valign="top">
4261 <classname>hash_standard_resize_policy</classname>
4264 <classname>Size_Policy</classname>
4267 <classname>hash_exponential_size_policy</classname>
4272 <entry valign="top">
4273 <classname>Trigger_Policy</classname>
4276 <classname>hash_load_check_resize_trigger</classname> with
4277 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4287 <section xml:id="multimap.text_find_small.observations">
4292 <para>See Observations::Mapping-Semantics
4293 Considerations.</para>
4299 <!-- 02 <a href="multimap_text_find_timing_test_large"> -->
4300 <section xml:id="performance.multimap.text_find_large">
4302 Text <function>find</function> with Large Secondary-to-Primary Key Ratios
4306 <section xml:id="multimap.text_find_large.info">
4311 <para>This test inserts a number of pairs into a container. The
4312 first item of each pair is a string from an arbitrary text
4313 ([wickland96thirty]), and
4314 the second is a uniform integer. The container is a
4315 "multimap" - it considers the first member of each pair as a
4316 primary key, and the second member of each pair as a secondary
4318 are 400 distinct primary keys, and the ratio of secondary keys
4319 to primary keys ranges from 1 to 5.</para>
4320 <para>The test measures the average find-time as a function of the
4321 number of values inserted. For this library's containers, it
4322 finds the secondary key from a container obtained from finding
4323 a primary key. For the native multimaps, it searches a range
4324 obtained using <classname>std::equal_range</classname> on a primary key.</para>
4327 It uses the test file:
4328 <filename>performance/ext/pb_ds/multimap_text_find_timing_large.cc</filename>
4331 <para>The test checks the find-time scalability of different
4332 "multimap" designs.</para>
4336 <section xml:id="multimap.text_find_large.results">
4341 <para>The graphic below show the results for "multimaps" which
4342 use a tree-based container for primary keys.
4345 <!-- results graphic -->
4349 <imagedata align="center" format="PNG" scale="100"
4350 fileref="../images/pbds_multimap_text_find_large_s2p_tree.png"/>
4353 <imagedata align="center" format="PDF" scale="33"
4354 fileref="../images/pbds_multimap_text_find_large_s2p_tree.pdf"/>
4360 The abbreviated names in the legend of the graphic above are
4361 instantiated with the types in the following table.
4365 <informaltable frame="all">
4367 <tgroup cols="7" align="left" colsep="1" rowsep="1">
4368 <colspec colname="c1"/>
4369 <colspec colname="c2"/>
4370 <colspec colname="c3"/>
4371 <colspec colname="c4"/>
4372 <colspec colname="c5"/>
4373 <colspec colname="c6"/>
4374 <colspec colname="c7"/>
4377 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
4378 <entry><emphasis>Parameter</emphasis></entry>
4379 <entry><emphasis>Details</emphasis></entry>
4380 <entry><emphasis>Parameter</emphasis></entry>
4381 <entry><emphasis>Details</emphasis></entry>
4382 <entry><emphasis>Parameter</emphasis></entry>
4383 <entry><emphasis>Details</emphasis></entry>
4391 <?dbhtml bgcolor="#B0B0B0" ?>
4392 <entry namest="c1" nameend="c7">
4399 <classname>std::multimap</classname>
4401 <entry namest="c2" nameend="c7"></entry>
4404 <!-- multimap 01 -->
4406 <?dbhtml bgcolor="#B0B0B0" ?>
4407 <entry namest="c1" nameend="c7">
4408 rb_tree_mmap_lu_mtf_set
4413 <entry morerows="2" valign="top">
4414 <classname>tree</classname>
4417 <classname>Tag</classname>
4420 <classname>rb_tree_tag</classname>
4422 <entry namest="c4" nameend="c7"></entry>
4427 <classname>Node_Update</classname>
4430 <classname>null_node_update</classname>
4432 <entry namest="c4" nameend="c7"></entry>
4436 <classname>Mapped</classname>
4439 <classname>list_update</classname>
4442 <classname>Update_Policy</classname>
4445 <classname>lu_move_to_front_policy</classname>
4447 <entry namest="c6" nameend="c7"></entry>
4450 <!-- multimap 02 -->
4452 <?dbhtml bgcolor="#B0B0B0" ?>
4453 <entry namest="c1" nameend="c7">
4454 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
4459 <entry morerows="4" valign="top">
4460 <classname>tree</classname>
4463 <classname>Tag</classname>
4466 <classname>rb_tree_tag</classname>
4468 <entry namest="c4" nameend="c7"></entry>
4473 <classname>Node_Update</classname>
4476 <classname>null_node_update</classname>
4478 <entry namest="c4" nameend="c7"></entry>
4482 <entry morerows="2" valign="top">
4483 <classname>Mapped</classname>
4485 <entry morerows="2" valign="top">
4486 <classname>cc_hash_table</classname>
4489 <classname>Comb_Hash_Fn</classname>
4492 <classname>direct_mask_range_hashing</classname>
4494 <entry namest="c6" nameend="c7"></entry>
4498 <entry morerows="1" valign="top">
4499 <classname>Resize_Policy</classname>
4501 <entry morerows="1" valign="top">
4502 <classname>hash_standard_resize_policy</classname>
4505 <classname>Size_Policy</classname>
4508 <classname>hash_exponential_size_policy</classname>
4513 <entry valign="top">
4514 <classname>Trigger_Policy</classname>
4517 <classname>hash_load_check_resize_trigger</classname> with
4518 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4527 <para>The graphic below show the results for "multimaps" which
4528 use a hash-based container for primary keys.
4531 <!-- results graphic -->
4535 <imagedata align="center" format="PNG" scale="100"
4536 fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
4539 <imagedata align="center" format="PDF" scale="33"
4540 fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
4546 The abbreviated names in the legend of the graphic above are
4547 instantiated with the types in the following table.
4550 <informaltable frame="all">
4552 <tgroup cols="7" align="left" colsep="1" rowsep="1">
4553 <colspec colname="c1"/>
4554 <colspec colname="c2"/>
4555 <colspec colname="c3"/>
4556 <colspec colname="c4"/>
4557 <colspec colname="c5"/>
4558 <colspec colname="c6"/>
4559 <colspec colname="c7"/>
4562 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
4563 <entry><emphasis>Parameter</emphasis></entry>
4564 <entry><emphasis>Details</emphasis></entry>
4565 <entry><emphasis>Parameter</emphasis></entry>
4566 <entry><emphasis>Details</emphasis></entry>
4567 <entry><emphasis>Parameter</emphasis></entry>
4568 <entry><emphasis>Details</emphasis></entry>
4576 <?dbhtml bgcolor="#B0B0B0" ?>
4577 <entry namest="c1" nameend="c7">
4584 <classname>std::tr1::unordered_multimap</classname>
4586 <entry namest="c2" nameend="c7"></entry>
4589 <!-- multimap 01 -->
4591 <?dbhtml bgcolor="#B0B0B0" ?>
4592 <entry namest="c1" nameend="c7">
4593 rb_tree_mmap_lu_mtf_set
4598 <entry morerows="3" valign="top">
4604 <classname>Comb_Hash_Fn</classname>
4607 <classname>direct_mask_range_hashing</classname>
4609 <entry namest="c4" nameend="c7"></entry>
4612 <entry morerows="1" valign="top">
4613 <classname>Resize_Policy</classname>
4615 <entry morerows="1" valign="top">
4616 <classname>hash_standard_resize_policy</classname>
4619 <classname>Size_Policy</classname>
4622 <classname>hash_exponential_size_policy</classname>
4624 <entry namest="c6" nameend="c7"></entry>
4628 <entry valign="top">
4629 <classname>Trigger_Policy</classname>
4632 <classname>hash_load_check_resize_trigger</classname> with
4633 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4635 <entry namest="c6" nameend="c7"></entry>
4640 <classname>Mapped</classname>
4643 <classname>list_update</classname>
4646 <classname>Update_Policy</classname>
4649 <classname>lu_move_to_front_policy</classname>
4651 <entry namest="c6" nameend="c7"></entry>
4654 <!-- multimap 02 -->
4656 <?dbhtml bgcolor="#B0B0B0" ?>
4657 <entry namest="c1" nameend="c7">
4658 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
4663 <entry morerows="5" valign="top">
4669 <classname>Comb_Hash_Fn</classname>
4672 <classname>direct_mask_range_hashing</classname>
4674 <entry namest="c4" nameend="c7"></entry>
4677 <entry morerows="1" valign="top">
4678 <classname>Resize_Policy</classname>
4680 <entry morerows="1" valign="top">
4681 <classname>hash_standard_resize_policy</classname>
4684 <classname>Size_Policy</classname>
4687 <classname>hash_exponential_size_policy</classname>
4689 <entry namest="c6" nameend="c7"></entry>
4693 <entry valign="top">
4694 <classname>Trigger_Policy</classname>
4697 <classname>hash_load_check_resize_trigger</classname> with
4698 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4700 <entry namest="c6" nameend="c7"></entry>
4704 <entry morerows="2" valign="top">
4705 <classname>Mapped</classname>
4707 <entry morerows="2" valign="top">
4708 <classname>cc_hash_table</classname>
4711 <classname>Comb_Hash_Fn</classname>
4714 <classname>direct_mask_range_hashing</classname>
4716 <entry namest="c6" nameend="c7"></entry>
4720 <entry morerows="1" valign="top">
4721 <classname>Resize_Policy</classname>
4723 <entry morerows="1" valign="top">
4724 <classname>hash_standard_resize_policy</classname>
4727 <classname>Size_Policy</classname>
4730 <classname>hash_exponential_size_policy</classname>
4735 <entry valign="top">
4736 <classname>Trigger_Policy</classname>
4739 <classname>hash_load_check_resize_trigger</classname> with
4740 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4750 <section xml:id="multimap.text_find_large.observations">
4755 <para>See Observations::Mapping-Semantics
4756 Considerations.</para>
4763 <!-- 03 <a href="multimap_text_insert_timing_test_small"> -->
4764 <section xml:id="performance.multimap.text_insert_small">
4766 Text <function>insert</function> with Small
4767 Secondary-to-Primary Key Ratios
4771 <section xml:id="multimap.text_insert_small.info">
4776 <para>This test inserts a number of pairs into a container. The
4777 first item of each pair is a string from an arbitrary text
4778 ([wickland96thirty]), and
4779 the second is a uniform integer. The container is a
4780 "multimap" - it considers the first member of each pair as a
4781 primary key, and the second member of each pair as a secondary
4783 are 400 distinct primary keys, and the ratio of secondary keys
4784 to primary keys ranges from 1 to 5.</para>
4785 <para>The test measures the average insert-time as a function of
4786 the number of values inserted. For this library's containers,
4787 it inserts a primary key into the primary associative
4788 container, then a secondary key into the secondary associative
4789 container. For the native multimaps, it obtains a range using
4790 <classname>std::equal_range</classname>, and inserts a value only if it was
4791 not contained already.</para>
4794 It uses the test file:
4795 <filename>performance/ext/pb_ds/multimap_text_insert_timing_small.cc</filename>
4798 <para>The test checks the insert-time scalability of different
4799 "multimap" designs.</para>
4803 <section xml:id="multimap.text_insert_small.results">
4808 <para>The graphic below show the results for "multimaps" which
4809 use a tree-based container for primary keys.
4812 <!-- results graphic -->
4816 <imagedata align="center" format="PNG" scale="100"
4817 fileref="../images/pbds_multimap_text_insert_small_s2p_tree.png"/>
4820 <imagedata align="center" format="PDF" scale="33"
4821 fileref="../images/pbds_multimap_text_insert_small_s2p_tree.pdf"/>
4827 The abbreviated names in the legend of the graphic above are
4828 instantiated with the types in the following table.
4832 <informaltable frame="all">
4834 <tgroup cols="7" align="left" colsep="1" rowsep="1">
4835 <colspec colname="c1"/>
4836 <colspec colname="c2"/>
4837 <colspec colname="c3"/>
4838 <colspec colname="c4"/>
4839 <colspec colname="c5"/>
4840 <colspec colname="c6"/>
4841 <colspec colname="c7"/>
4844 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
4845 <entry><emphasis>Parameter</emphasis></entry>
4846 <entry><emphasis>Details</emphasis></entry>
4847 <entry><emphasis>Parameter</emphasis></entry>
4848 <entry><emphasis>Details</emphasis></entry>
4849 <entry><emphasis>Parameter</emphasis></entry>
4850 <entry><emphasis>Details</emphasis></entry>
4858 <?dbhtml bgcolor="#B0B0B0" ?>
4859 <entry namest="c1" nameend="c7">
4866 <classname>std::multimap</classname>
4868 <entry namest="c2" nameend="c7"></entry>
4871 <!-- multimap 01 -->
4873 <?dbhtml bgcolor="#B0B0B0" ?>
4874 <entry namest="c1" nameend="c7">
4875 rb_tree_mmap_lu_mtf_set
4880 <entry morerows="2" valign="top">
4881 <classname>tree</classname>
4884 <classname>Tag</classname>
4887 <classname>rb_tree_tag</classname>
4889 <entry namest="c4" nameend="c7"></entry>
4894 <classname>Node_Update</classname>
4897 <classname>null_node_update</classname>
4899 <entry namest="c4" nameend="c7"></entry>
4903 <classname>Mapped</classname>
4906 <classname>list_update</classname>
4909 <classname>Update_Policy</classname>
4912 <classname>lu_move_to_front_policy</classname>
4914 <entry namest="c6" nameend="c7"></entry>
4917 <!-- multimap 02 -->
4919 <?dbhtml bgcolor="#B0B0B0" ?>
4920 <entry namest="c1" nameend="c7">
4921 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
4926 <entry morerows="4" valign="top">
4927 <classname>tree</classname>
4930 <classname>Tag</classname>
4933 <classname>rb_tree_tag</classname>
4935 <entry namest="c4" nameend="c7"></entry>
4940 <classname>Node_Update</classname>
4943 <classname>null_node_update</classname>
4945 <entry namest="c4" nameend="c7"></entry>
4949 <entry morerows="2" valign="top">
4950 <classname>Mapped</classname>
4952 <entry morerows="2" valign="top">
4953 <classname>cc_hash_table</classname>
4956 <classname>Comb_Hash_Fn</classname>
4959 <classname>direct_mask_range_hashing</classname>
4961 <entry namest="c6" nameend="c7"></entry>
4965 <entry morerows="1" valign="top">
4966 <classname>Resize_Policy</classname>
4968 <entry morerows="1" valign="top">
4969 <classname>hash_standard_resize_policy</classname>
4972 <classname>Size_Policy</classname>
4975 <classname>hash_exponential_size_policy</classname>
4980 <entry valign="top">
4981 <classname>Trigger_Policy</classname>
4984 <classname>hash_load_check_resize_trigger</classname> with
4985 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
4994 <para>The graphic below show the results for "multimaps" which
4995 use a hash-based container for primary keys.
4998 <!-- results graphic -->
5002 <imagedata align="center" format="PNG" scale="100"
5003 fileref="../images/pbds_multimap_text_find_small_s2p_hash.png"/>
5006 <imagedata align="center" format="PDF" scale="33"
5007 fileref="../images/pbds_multimap_text_find_small_s2p_hash.pdf"/>
5013 The abbreviated names in the legend of the graphic above are
5014 instantiated with the types in the following table.
5017 <informaltable frame="all">
5019 <tgroup cols="7" align="left" colsep="1" rowsep="1">
5020 <colspec colname="c1"/>
5021 <colspec colname="c2"/>
5022 <colspec colname="c3"/>
5023 <colspec colname="c4"/>
5024 <colspec colname="c5"/>
5025 <colspec colname="c6"/>
5026 <colspec colname="c7"/>
5029 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
5030 <entry><emphasis>Parameter</emphasis></entry>
5031 <entry><emphasis>Details</emphasis></entry>
5032 <entry><emphasis>Parameter</emphasis></entry>
5033 <entry><emphasis>Details</emphasis></entry>
5034 <entry><emphasis>Parameter</emphasis></entry>
5035 <entry><emphasis>Details</emphasis></entry>
5043 <?dbhtml bgcolor="#B0B0B0" ?>
5044 <entry namest="c1" nameend="c7">
5051 <classname>std::tr1::unordered_multimap</classname>
5053 <entry namest="c2" nameend="c7"></entry>
5056 <!-- multimap 01 -->
5058 <?dbhtml bgcolor="#B0B0B0" ?>
5059 <entry namest="c1" nameend="c7">
5060 rb_tree_mmap_lu_mtf_set
5065 <entry morerows="3" valign="top">
5071 <classname>Comb_Hash_Fn</classname>
5074 <classname>direct_mask_range_hashing</classname>
5076 <entry namest="c4" nameend="c7"></entry>
5079 <entry morerows="1" valign="top">
5080 <classname>Resize_Policy</classname>
5082 <entry morerows="1" valign="top">
5083 <classname>hash_standard_resize_policy</classname>
5086 <classname>Size_Policy</classname>
5089 <classname>hash_exponential_size_policy</classname>
5091 <entry namest="c6" nameend="c7"></entry>
5095 <entry valign="top">
5096 <classname>Trigger_Policy</classname>
5099 <classname>hash_load_check_resize_trigger</classname> with
5100 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5102 <entry namest="c6" nameend="c7"></entry>
5107 <classname>Mapped</classname>
5110 <classname>list_update</classname>
5113 <classname>Update_Policy</classname>
5116 <classname>lu_move_to_front_policy</classname>
5118 <entry namest="c6" nameend="c7"></entry>
5121 <!-- multimap 02 -->
5123 <?dbhtml bgcolor="#B0B0B0" ?>
5124 <entry namest="c1" nameend="c7">
5125 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
5130 <entry morerows="5" valign="top">
5136 <classname>Comb_Hash_Fn</classname>
5139 <classname>direct_mask_range_hashing</classname>
5141 <entry namest="c4" nameend="c7"></entry>
5144 <entry morerows="1" valign="top">
5145 <classname>Resize_Policy</classname>
5147 <entry morerows="1" valign="top">
5148 <classname>hash_standard_resize_policy</classname>
5151 <classname>Size_Policy</classname>
5154 <classname>hash_exponential_size_policy</classname>
5156 <entry namest="c6" nameend="c7"></entry>
5160 <entry valign="top">
5161 <classname>Trigger_Policy</classname>
5164 <classname>hash_load_check_resize_trigger</classname> with
5165 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5167 <entry namest="c6" nameend="c7"></entry>
5171 <entry morerows="2" valign="top">
5172 <classname>Mapped</classname>
5174 <entry morerows="2" valign="top">
5175 <classname>cc_hash_table</classname>
5178 <classname>Comb_Hash_Fn</classname>
5181 <classname>direct_mask_range_hashing</classname>
5183 <entry namest="c6" nameend="c7"></entry>
5187 <entry morerows="1" valign="top">
5188 <classname>Resize_Policy</classname>
5190 <entry morerows="1" valign="top">
5191 <classname>hash_standard_resize_policy</classname>
5194 <classname>Size_Policy</classname>
5197 <classname>hash_exponential_size_policy</classname>
5202 <entry valign="top">
5203 <classname>Trigger_Policy</classname>
5206 <classname>hash_load_check_resize_trigger</classname> with
5207 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5217 <section xml:id="multimap.text_insert_small.observations">
5222 <para>See Observations::Mapping-Semantics
5223 Considerations.</para>
5230 <!-- 04 <a href="multimap_text_insert_timing_test_large"> -->
5231 <section xml:id="performance.multimap.text_insert_large">
5233 Text <function>insert</function> with Small
5234 Secondary-to-Primary Key Ratios
5238 <section xml:id="multimap.text_insert_large.info">
5243 <para>This test inserts a number of pairs into a container. The
5244 first item of each pair is a string from an arbitrary text
5245 ([wickland96thirty]), and
5246 the second is a uniform integer. The container is a
5247 "multimap" - it considers the first member of each pair as a
5248 primary key, and the second member of each pair as a secondary
5250 are 400 distinct primary keys, and the ratio of secondary keys
5251 to primary keys ranges from 1 to 5.</para>
5252 <para>The test measures the average insert-time as a function of
5253 the number of values inserted. For this library's containers,
5254 it inserts a primary key into the primary associative
5255 container, then a secondary key into the secondary associative
5256 container. For the native multimaps, it obtains a range using
5257 <classname>std::equal_range</classname>, and inserts a value only if it was
5258 not contained already.</para>
5261 It uses the test file:
5262 <filename>performance/ext/pb_ds/multimap_text_insert_timing_large.cc</filename>
5265 <para>The test checks the insert-time scalability of different
5266 "multimap" designs.</para>
5270 <section xml:id="multimap.text_insert_large.results">
5275 <para>The graphic below show the results for "multimaps" which
5276 use a tree-based container for primary keys.
5279 <!-- results graphic -->
5283 <imagedata align="center" format="PNG" scale="100"
5284 fileref="../images/pbds_multimap_text_insert_large_s2p_tree.png"/>
5287 <imagedata align="center" format="PDF" scale="33"
5288 fileref="../images/pbds_multimap_text_insert_large_s2p_tree.pdf"/>
5294 The abbreviated names in the legend of the graphic above are
5295 instantiated with the types in the following table.
5299 <informaltable frame="all">
5301 <tgroup cols="7" align="left" colsep="1" rowsep="1">
5302 <colspec colname="c1"/>
5303 <colspec colname="c2"/>
5304 <colspec colname="c3"/>
5305 <colspec colname="c4"/>
5306 <colspec colname="c5"/>
5307 <colspec colname="c6"/>
5308 <colspec colname="c7"/>
5311 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
5312 <entry><emphasis>Parameter</emphasis></entry>
5313 <entry><emphasis>Details</emphasis></entry>
5314 <entry><emphasis>Parameter</emphasis></entry>
5315 <entry><emphasis>Details</emphasis></entry>
5316 <entry><emphasis>Parameter</emphasis></entry>
5317 <entry><emphasis>Details</emphasis></entry>
5325 <?dbhtml bgcolor="#B0B0B0" ?>
5326 <entry namest="c1" nameend="c7">
5333 <classname>std::multimap</classname>
5335 <entry namest="c2" nameend="c7"></entry>
5338 <!-- multimap 01 -->
5340 <?dbhtml bgcolor="#B0B0B0" ?>
5341 <entry namest="c1" nameend="c7">
5342 rb_tree_mmap_lu_mtf_set
5347 <entry morerows="2" valign="top">
5348 <classname>tree</classname>
5351 <classname>Tag</classname>
5354 <classname>rb_tree_tag</classname>
5356 <entry namest="c4" nameend="c7"></entry>
5361 <classname>Node_Update</classname>
5364 <classname>null_node_update</classname>
5366 <entry namest="c4" nameend="c7"></entry>
5370 <classname>Mapped</classname>
5373 <classname>list_update</classname>
5376 <classname>Update_Policy</classname>
5379 <classname>lu_move_to_front_policy</classname>
5381 <entry namest="c6" nameend="c7"></entry>
5384 <!-- multimap 02 -->
5386 <?dbhtml bgcolor="#B0B0B0" ?>
5387 <entry namest="c1" nameend="c7">
5388 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
5393 <entry morerows="4" valign="top">
5394 <classname>tree</classname>
5397 <classname>Tag</classname>
5400 <classname>rb_tree_tag</classname>
5402 <entry namest="c4" nameend="c7"></entry>
5407 <classname>Node_Update</classname>
5410 <classname>null_node_update</classname>
5412 <entry namest="c4" nameend="c7"></entry>
5416 <entry morerows="2" valign="top">
5417 <classname>Mapped</classname>
5419 <entry morerows="2" valign="top">
5420 <classname>cc_hash_table</classname>
5423 <classname>Comb_Hash_Fn</classname>
5426 <classname>direct_mask_range_hashing</classname>
5428 <entry namest="c6" nameend="c7"></entry>
5432 <entry morerows="1" valign="top">
5433 <classname>Resize_Policy</classname>
5435 <entry morerows="1" valign="top">
5436 <classname>hash_standard_resize_policy</classname>
5439 <classname>Size_Policy</classname>
5442 <classname>hash_exponential_size_policy</classname>
5447 <entry valign="top">
5448 <classname>Trigger_Policy</classname>
5451 <classname>hash_load_check_resize_trigger</classname> with
5452 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5461 <para>The graphic below show the results for "multimaps" which
5462 use a hash-based container for primary keys.
5465 <!-- results graphic -->
5469 <imagedata align="center" format="PNG" scale="100"
5470 fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
5473 <imagedata align="center" format="PDF" scale="33"
5474 fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
5480 The abbreviated names in the legend of the graphic above are
5481 instantiated with the types in the following table.
5484 <informaltable frame="all">
5486 <tgroup cols="7" align="left" colsep="1" rowsep="1">
5487 <colspec colname="c1"/>
5488 <colspec colname="c2"/>
5489 <colspec colname="c3"/>
5490 <colspec colname="c4"/>
5491 <colspec colname="c5"/>
5492 <colspec colname="c6"/>
5493 <colspec colname="c7"/>
5496 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
5497 <entry><emphasis>Parameter</emphasis></entry>
5498 <entry><emphasis>Details</emphasis></entry>
5499 <entry><emphasis>Parameter</emphasis></entry>
5500 <entry><emphasis>Details</emphasis></entry>
5501 <entry><emphasis>Parameter</emphasis></entry>
5502 <entry><emphasis>Details</emphasis></entry>
5510 <?dbhtml bgcolor="#B0B0B0" ?>
5511 <entry namest="c1" nameend="c7">
5518 <classname>std::tr1::unordered_multimap</classname>
5520 <entry namest="c2" nameend="c7"></entry>
5523 <!-- multimap 01 -->
5525 <?dbhtml bgcolor="#B0B0B0" ?>
5526 <entry namest="c1" nameend="c7">
5527 rb_tree_mmap_lu_mtf_set
5532 <entry morerows="3" valign="top">
5538 <classname>Comb_Hash_Fn</classname>
5541 <classname>direct_mask_range_hashing</classname>
5543 <entry namest="c4" nameend="c7"></entry>
5546 <entry morerows="1" valign="top">
5547 <classname>Resize_Policy</classname>
5549 <entry morerows="1" valign="top">
5550 <classname>hash_standard_resize_policy</classname>
5553 <classname>Size_Policy</classname>
5556 <classname>hash_exponential_size_policy</classname>
5558 <entry namest="c6" nameend="c7"></entry>
5562 <entry valign="top">
5563 <classname>Trigger_Policy</classname>
5566 <classname>hash_load_check_resize_trigger</classname> with
5567 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5569 <entry namest="c6" nameend="c7"></entry>
5574 <classname>Mapped</classname>
5577 <classname>list_update</classname>
5580 <classname>Update_Policy</classname>
5583 <classname>lu_move_to_front_policy</classname>
5585 <entry namest="c6" nameend="c7"></entry>
5588 <!-- multimap 02 -->
5590 <?dbhtml bgcolor="#B0B0B0" ?>
5591 <entry namest="c1" nameend="c7">
5592 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
5597 <entry morerows="5" valign="top">
5603 <classname>Comb_Hash_Fn</classname>
5606 <classname>direct_mask_range_hashing</classname>
5608 <entry namest="c4" nameend="c7"></entry>
5611 <entry morerows="1" valign="top">
5612 <classname>Resize_Policy</classname>
5614 <entry morerows="1" valign="top">
5615 <classname>hash_standard_resize_policy</classname>
5618 <classname>Size_Policy</classname>
5621 <classname>hash_exponential_size_policy</classname>
5623 <entry namest="c6" nameend="c7"></entry>
5627 <entry valign="top">
5628 <classname>Trigger_Policy</classname>
5631 <classname>hash_load_check_resize_trigger</classname> with
5632 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5634 <entry namest="c6" nameend="c7"></entry>
5638 <entry morerows="2" valign="top">
5639 <classname>Mapped</classname>
5641 <entry morerows="2" valign="top">
5642 <classname>cc_hash_table</classname>
5645 <classname>Comb_Hash_Fn</classname>
5648 <classname>direct_mask_range_hashing</classname>
5650 <entry namest="c6" nameend="c7"></entry>
5654 <entry morerows="1" valign="top">
5655 <classname>Resize_Policy</classname>
5657 <entry morerows="1" valign="top">
5658 <classname>hash_standard_resize_policy</classname>
5661 <classname>Size_Policy</classname>
5664 <classname>hash_exponential_size_policy</classname>
5669 <entry valign="top">
5670 <classname>Trigger_Policy</classname>
5673 <classname>hash_load_check_resize_trigger</classname> with
5674 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5684 <section xml:id="multimap.text_insert_large.observations">
5689 <para>See Observations::Mapping-Semantics
5690 Considerations.</para>
5697 <!-- 05 <a href="multimap_text_insert_mem_usage_test_small"> -->
5698 <section xml:id="performance.multimap.text_insert_mem_small">
5700 Text <function>insert</function> with Small
5701 Secondary-to-Primary Key Ratios Memory Use
5705 <section xml:id="multimap.text_insert_mem_small.info">
5709 <para>This test inserts a number of pairs into a container. The
5710 first item of each pair is a string from an arbitrary text
5711 ([wickland96thirty]), and
5712 the second is a uniform integer. The container is a
5713 "multimap" - it considers the first member of each pair as a
5714 primary key, and the second member of each pair as a secondary
5716 are 100 distinct primary keys, and the ratio of secondary keys
5717 to primary keys ranges to about 20.</para>
5718 <para>The test measures the memory use as a function of the number
5719 of values inserted.</para>
5722 It uses the test file:
5723 <filename>performance/ext/pb_ds/multimap_text_insert_mem_usage_small.cc</filename>
5726 <para>The test checks the memory scalability of different
5727 "multimap" designs.</para>
5731 <section xml:id="multimap.text_insert_mem_small.results">
5736 <para>The graphic below show the results for "multimaps" which
5737 use a tree-based container for primary keys.
5740 <!-- results graphic -->
5744 <imagedata align="center" format="PNG" scale="100"
5745 fileref="../images/pbds_multimap_text_insert_mem_small_s2p_tree.png"/>
5748 <imagedata align="center" format="PDF" scale="33"
5749 fileref="../images/pbds_multimap_text_insert_mem_small_s2p_tree.pdf"/>
5755 The abbreviated names in the legend of the graphic above are
5756 instantiated with the types in the following table.
5760 <informaltable frame="all">
5762 <tgroup cols="7" align="left" colsep="1" rowsep="1">
5763 <colspec colname="c1"/>
5764 <colspec colname="c2"/>
5765 <colspec colname="c3"/>
5766 <colspec colname="c4"/>
5767 <colspec colname="c5"/>
5768 <colspec colname="c6"/>
5769 <colspec colname="c7"/>
5772 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
5773 <entry><emphasis>Parameter</emphasis></entry>
5774 <entry><emphasis>Details</emphasis></entry>
5775 <entry><emphasis>Parameter</emphasis></entry>
5776 <entry><emphasis>Details</emphasis></entry>
5777 <entry><emphasis>Parameter</emphasis></entry>
5778 <entry><emphasis>Details</emphasis></entry>
5786 <?dbhtml bgcolor="#B0B0B0" ?>
5787 <entry namest="c1" nameend="c7">
5794 <classname>std::multimap</classname>
5796 <entry namest="c2" nameend="c7"></entry>
5799 <!-- multimap 01 -->
5801 <?dbhtml bgcolor="#B0B0B0" ?>
5802 <entry namest="c1" nameend="c7">
5803 rb_tree_mmap_lu_mtf_set
5808 <entry morerows="2" valign="top">
5809 <classname>tree</classname>
5812 <classname>Tag</classname>
5815 <classname>rb_tree_tag</classname>
5817 <entry namest="c4" nameend="c7"></entry>
5822 <classname>Node_Update</classname>
5825 <classname>null_node_update</classname>
5827 <entry namest="c4" nameend="c7"></entry>
5831 <classname>Mapped</classname>
5834 <classname>list_update</classname>
5837 <classname>Update_Policy</classname>
5840 <classname>lu_move_to_front_policy</classname>
5842 <entry namest="c6" nameend="c7"></entry>
5845 <!-- multimap 02 -->
5847 <?dbhtml bgcolor="#B0B0B0" ?>
5848 <entry namest="c1" nameend="c7">
5849 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
5854 <entry morerows="4" valign="top">
5855 <classname>tree</classname>
5858 <classname>Tag</classname>
5861 <classname>rb_tree_tag</classname>
5863 <entry namest="c4" nameend="c7"></entry>
5868 <classname>Node_Update</classname>
5871 <classname>null_node_update</classname>
5873 <entry namest="c4" nameend="c7"></entry>
5877 <entry morerows="2" valign="top">
5878 <classname>Mapped</classname>
5880 <entry morerows="2" valign="top">
5881 <classname>cc_hash_table</classname>
5884 <classname>Comb_Hash_Fn</classname>
5887 <classname>direct_mask_range_hashing</classname>
5889 <entry namest="c6" nameend="c7"></entry>
5893 <entry morerows="1" valign="top">
5894 <classname>Resize_Policy</classname>
5896 <entry morerows="1" valign="top">
5897 <classname>hash_standard_resize_policy</classname>
5900 <classname>Size_Policy</classname>
5903 <classname>hash_exponential_size_policy</classname>
5908 <entry valign="top">
5909 <classname>Trigger_Policy</classname>
5912 <classname>hash_load_check_resize_trigger</classname> with
5913 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
5922 <para>The graphic below show the results for "multimaps" which
5923 use a hash-based container for primary keys.
5926 <!-- results graphic -->
5930 <imagedata align="center" format="PNG" scale="100"
5931 fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
5934 <imagedata align="center" format="PDF" scale="33"
5935 fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
5941 The abbreviated names in the legend of the graphic above are
5942 instantiated with the types in the following table.
5945 <informaltable frame="all">
5947 <tgroup cols="7" align="left" colsep="1" rowsep="1">
5948 <colspec colname="c1"/>
5949 <colspec colname="c2"/>
5950 <colspec colname="c3"/>
5951 <colspec colname="c4"/>
5952 <colspec colname="c5"/>
5953 <colspec colname="c6"/>
5954 <colspec colname="c7"/>
5957 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
5958 <entry><emphasis>Parameter</emphasis></entry>
5959 <entry><emphasis>Details</emphasis></entry>
5960 <entry><emphasis>Parameter</emphasis></entry>
5961 <entry><emphasis>Details</emphasis></entry>
5962 <entry><emphasis>Parameter</emphasis></entry>
5963 <entry><emphasis>Details</emphasis></entry>
5971 <?dbhtml bgcolor="#B0B0B0" ?>
5972 <entry namest="c1" nameend="c7">
5979 <classname>std::tr1::unordered_multimap</classname>
5981 <entry namest="c2" nameend="c7"></entry>
5984 <!-- multimap 01 -->
5986 <?dbhtml bgcolor="#B0B0B0" ?>
5987 <entry namest="c1" nameend="c7">
5988 rb_tree_mmap_lu_mtf_set
5993 <entry morerows="3" valign="top">
5999 <classname>Comb_Hash_Fn</classname>
6002 <classname>direct_mask_range_hashing</classname>
6004 <entry namest="c4" nameend="c7"></entry>
6007 <entry morerows="1" valign="top">
6008 <classname>Resize_Policy</classname>
6010 <entry morerows="1" valign="top">
6011 <classname>hash_standard_resize_policy</classname>
6014 <classname>Size_Policy</classname>
6017 <classname>hash_exponential_size_policy</classname>
6019 <entry namest="c6" nameend="c7"></entry>
6023 <entry valign="top">
6024 <classname>Trigger_Policy</classname>
6027 <classname>hash_load_check_resize_trigger</classname> with
6028 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6030 <entry namest="c6" nameend="c7"></entry>
6035 <classname>Mapped</classname>
6038 <classname>list_update</classname>
6041 <classname>Update_Policy</classname>
6044 <classname>lu_move_to_front_policy</classname>
6046 <entry namest="c6" nameend="c7"></entry>
6049 <!-- multimap 02 -->
6051 <?dbhtml bgcolor="#B0B0B0" ?>
6052 <entry namest="c1" nameend="c7">
6053 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
6058 <entry morerows="5" valign="top">
6064 <classname>Comb_Hash_Fn</classname>
6067 <classname>direct_mask_range_hashing</classname>
6069 <entry namest="c4" nameend="c7"></entry>
6072 <entry morerows="1" valign="top">
6073 <classname>Resize_Policy</classname>
6075 <entry morerows="1" valign="top">
6076 <classname>hash_standard_resize_policy</classname>
6079 <classname>Size_Policy</classname>
6082 <classname>hash_exponential_size_policy</classname>
6084 <entry namest="c6" nameend="c7"></entry>
6088 <entry valign="top">
6089 <classname>Trigger_Policy</classname>
6092 <classname>hash_load_check_resize_trigger</classname> with
6093 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6095 <entry namest="c6" nameend="c7"></entry>
6099 <entry morerows="2" valign="top">
6100 <classname>Mapped</classname>
6102 <entry morerows="2" valign="top">
6103 <classname>cc_hash_table</classname>
6106 <classname>Comb_Hash_Fn</classname>
6109 <classname>direct_mask_range_hashing</classname>
6111 <entry namest="c6" nameend="c7"></entry>
6115 <entry morerows="1" valign="top">
6116 <classname>Resize_Policy</classname>
6118 <entry morerows="1" valign="top">
6119 <classname>hash_standard_resize_policy</classname>
6122 <classname>Size_Policy</classname>
6125 <classname>hash_exponential_size_policy</classname>
6130 <entry valign="top">
6131 <classname>Trigger_Policy</classname>
6134 <classname>hash_load_check_resize_trigger</classname> with
6135 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6145 <section xml:id="multimap.text_insert_mem_small.observations">
6150 <para>See Observations::Mapping-Semantics
6151 Considerations.</para>
6157 <!-- 06 <a href="multimap_text_insert_mem_usage_test_large"> -->
6158 <section xml:id="performance.multimap.text_insert_mem_large">
6160 Text <function>insert</function> with Small
6161 Secondary-to-Primary Key Ratios Memory Use
6165 <section xml:id="multimap.text_insert_mem_large.info">
6169 <para>This test inserts a number of pairs into a container. The
6170 first item of each pair is a string from an arbitrary text
6171 ([wickland96thirty]), and
6172 the second is a uniform integer. The container is a
6173 "multimap" - it considers the first member of each pair as a
6174 primary key, and the second member of each pair as a secondary
6176 are 100 distinct primary keys, and the ratio of secondary keys
6177 to primary keys ranges to about 20.</para>
6178 <para>The test measures the memory use as a function of the number
6179 of values inserted.</para>
6182 It uses the test file:
6183 <filename>performance/ext/pb_ds/multimap_text_insert_mem_usage_large.cc</filename>
6186 <para>The test checks the memory scalability of different
6187 "multimap" designs.</para>
6191 <section xml:id="multimap.text_insert_mem_large.results">
6196 <para>The graphic below show the results for "multimaps" which
6197 use a tree-based container for primary keys.
6200 <!-- results graphic -->
6204 <imagedata align="center" format="PNG" scale="100"
6205 fileref="../images/pbds_multimap_text_insert_mem_large_s2p_tree.png"/>
6208 <imagedata align="center" format="PDF" scale="33"
6209 fileref="../images/pbds_multimap_text_insert_mem_large_s2p_tree.pdf"/>
6215 The abbreviated names in the legend of the graphic above are
6216 instantiated with the types in the following table.
6220 <informaltable frame="all">
6222 <tgroup cols="7" align="left" colsep="1" rowsep="1">
6223 <colspec colname="c1"/>
6224 <colspec colname="c2"/>
6225 <colspec colname="c3"/>
6226 <colspec colname="c4"/>
6227 <colspec colname="c5"/>
6228 <colspec colname="c6"/>
6229 <colspec colname="c7"/>
6232 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
6233 <entry><emphasis>Parameter</emphasis></entry>
6234 <entry><emphasis>Details</emphasis></entry>
6235 <entry><emphasis>Parameter</emphasis></entry>
6236 <entry><emphasis>Details</emphasis></entry>
6237 <entry><emphasis>Parameter</emphasis></entry>
6238 <entry><emphasis>Details</emphasis></entry>
6246 <?dbhtml bgcolor="#B0B0B0" ?>
6247 <entry namest="c1" nameend="c7">
6254 <classname>std::multimap</classname>
6256 <entry namest="c2" nameend="c7"></entry>
6259 <!-- multimap 01 -->
6261 <?dbhtml bgcolor="#B0B0B0" ?>
6262 <entry namest="c1" nameend="c7">
6263 rb_tree_mmap_lu_mtf_set
6268 <entry morerows="2" valign="top">
6269 <classname>tree</classname>
6272 <classname>Tag</classname>
6275 <classname>rb_tree_tag</classname>
6277 <entry namest="c4" nameend="c7"></entry>
6282 <classname>Node_Update</classname>
6285 <classname>null_node_update</classname>
6287 <entry namest="c4" nameend="c7"></entry>
6291 <classname>Mapped</classname>
6294 <classname>list_update</classname>
6297 <classname>Update_Policy</classname>
6300 <classname>lu_move_to_front_policy</classname>
6302 <entry namest="c6" nameend="c7"></entry>
6305 <!-- multimap 02 -->
6307 <?dbhtml bgcolor="#B0B0B0" ?>
6308 <entry namest="c1" nameend="c7">
6309 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
6314 <entry morerows="4" valign="top">
6315 <classname>tree</classname>
6318 <classname>Tag</classname>
6321 <classname>rb_tree_tag</classname>
6323 <entry namest="c4" nameend="c7"></entry>
6328 <classname>Node_Update</classname>
6331 <classname>null_node_update</classname>
6333 <entry namest="c4" nameend="c7"></entry>
6337 <entry morerows="2" valign="top">
6338 <classname>Mapped</classname>
6340 <entry morerows="2" valign="top">
6341 <classname>cc_hash_table</classname>
6344 <classname>Comb_Hash_Fn</classname>
6347 <classname>direct_mask_range_hashing</classname>
6349 <entry namest="c6" nameend="c7"></entry>
6353 <entry morerows="1" valign="top">
6354 <classname>Resize_Policy</classname>
6356 <entry morerows="1" valign="top">
6357 <classname>hash_standard_resize_policy</classname>
6360 <classname>Size_Policy</classname>
6363 <classname>hash_exponential_size_policy</classname>
6368 <entry valign="top">
6369 <classname>Trigger_Policy</classname>
6372 <classname>hash_load_check_resize_trigger</classname> with
6373 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6382 <para>The graphic below show the results for "multimaps" which
6383 use a hash-based container for primary keys.
6386 <!-- results graphic -->
6390 <imagedata align="center" format="PNG" scale="100"
6391 fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
6394 <imagedata align="center" format="PDF" scale="33"
6395 fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
6401 The abbreviated names in the legend of the graphic above are
6402 instantiated with the types in the following table.
6405 <informaltable frame="all">
6407 <tgroup cols="7" align="left" colsep="1" rowsep="1">
6408 <colspec colname="c1"/>
6409 <colspec colname="c2"/>
6410 <colspec colname="c3"/>
6411 <colspec colname="c4"/>
6412 <colspec colname="c5"/>
6413 <colspec colname="c6"/>
6414 <colspec colname="c7"/>
6417 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
6418 <entry><emphasis>Parameter</emphasis></entry>
6419 <entry><emphasis>Details</emphasis></entry>
6420 <entry><emphasis>Parameter</emphasis></entry>
6421 <entry><emphasis>Details</emphasis></entry>
6422 <entry><emphasis>Parameter</emphasis></entry>
6423 <entry><emphasis>Details</emphasis></entry>
6431 <?dbhtml bgcolor="#B0B0B0" ?>
6432 <entry namest="c1" nameend="c7">
6439 <classname>std::tr1::unordered_multimap</classname>
6441 <entry namest="c2" nameend="c7"></entry>
6444 <!-- multimap 01 -->
6446 <?dbhtml bgcolor="#B0B0B0" ?>
6447 <entry namest="c1" nameend="c7">
6448 rb_tree_mmap_lu_mtf_set
6453 <entry morerows="3" valign="top">
6459 <classname>Comb_Hash_Fn</classname>
6462 <classname>direct_mask_range_hashing</classname>
6464 <entry namest="c4" nameend="c7"></entry>
6467 <entry morerows="1" valign="top">
6468 <classname>Resize_Policy</classname>
6470 <entry morerows="1" valign="top">
6471 <classname>hash_standard_resize_policy</classname>
6474 <classname>Size_Policy</classname>
6477 <classname>hash_exponential_size_policy</classname>
6479 <entry namest="c6" nameend="c7"></entry>
6483 <entry valign="top">
6484 <classname>Trigger_Policy</classname>
6487 <classname>hash_load_check_resize_trigger</classname> with
6488 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6490 <entry namest="c6" nameend="c7"></entry>
6495 <classname>Mapped</classname>
6498 <classname>list_update</classname>
6501 <classname>Update_Policy</classname>
6504 <classname>lu_move_to_front_policy</classname>
6506 <entry namest="c6" nameend="c7"></entry>
6509 <!-- multimap 02 -->
6511 <?dbhtml bgcolor="#B0B0B0" ?>
6512 <entry namest="c1" nameend="c7">
6513 rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
6518 <entry morerows="5" valign="top">
6524 <classname>Comb_Hash_Fn</classname>
6527 <classname>direct_mask_range_hashing</classname>
6529 <entry namest="c4" nameend="c7"></entry>
6532 <entry morerows="1" valign="top">
6533 <classname>Resize_Policy</classname>
6535 <entry morerows="1" valign="top">
6536 <classname>hash_standard_resize_policy</classname>
6539 <classname>Size_Policy</classname>
6542 <classname>hash_exponential_size_policy</classname>
6544 <entry namest="c6" nameend="c7"></entry>
6548 <entry valign="top">
6549 <classname>Trigger_Policy</classname>
6552 <classname>hash_load_check_resize_trigger</classname> with
6553 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6555 <entry namest="c6" nameend="c7"></entry>
6559 <entry morerows="2" valign="top">
6560 <classname>Mapped</classname>
6562 <entry morerows="2" valign="top">
6563 <classname>cc_hash_table</classname>
6566 <classname>Comb_Hash_Fn</classname>
6569 <classname>direct_mask_range_hashing</classname>
6571 <entry namest="c6" nameend="c7"></entry>
6575 <entry morerows="1" valign="top">
6576 <classname>Resize_Policy</classname>
6578 <entry morerows="1" valign="top">
6579 <classname>hash_standard_resize_policy</classname>
6582 <classname>Size_Policy</classname>
6585 <classname>hash_exponential_size_policy</classname>
6590 <entry valign="top">
6591 <classname>Trigger_Policy</classname>
6594 <classname>hash_load_check_resize_trigger</classname> with
6595 α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2
6605 <section xml:id="multimap.text_insert_mem_large.observations">
6610 <para>See Observations::Mapping-Semantics
6611 Considerations.</para>
6617 </section> <!-- multimap -->
6619 <section xml:id="performance.priority_queue">
6620 <info><title>Priority Queue</title></info>
6622 <!-- 01 <a href="priority_queue_text_push_timing_test"> -->
6623 <section xml:id="performance.priority_queue.text_push">
6625 Text <function>push</function>
6629 <section xml:id="priority_queue.text_push.info">
6635 <para>This test inserts a number of values with keys from an
6636 arbitrary text ([ wickland96thirty ]) into
6637 a container using <function>push</function>. It measures the average time
6638 for <function>push</function> as a function of the number of values
6642 It uses the test file:
6643 <filename>performance/ext/pb_ds/priority_queue_text_push_timing.cc</filename>
6646 <para>The test checks the effect of different underlying data
6652 <section xml:id="priority_queue.text_push.results">
6657 <para>The two graphics below show the results for the native
6658 priority_queues and this library's priority_queues.
6661 <para>The graphic immediately below shows the results for the
6662 native priority_queue type instantiated with different underlying
6663 container types versus several different versions of library's
6667 <!-- results graphic -->
6671 <imagedata align="center" format="PDF" scale="75"
6672 fileref="../images/pbds_priority_queue_text_push.pdf"/>
6675 <imagedata align="center" format="PNG" scale="100"
6676 fileref="../images/pbds_priority_queue_text_push.png"/>
6682 The abbreviated names in the legend of the graphic above are
6683 instantiated with the types in the following table.
6687 <informaltable frame="all">
6689 <tgroup cols="3" align="left" colsep="1" rowsep="1">
6690 <colspec colname="c1"/>
6691 <colspec colname="c2"/>
6692 <colspec colname="c3"/>
6695 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
6696 <entry><emphasis>Parameter</emphasis></entry>
6697 <entry><emphasis>Details</emphasis></entry>
6705 <?dbhtml bgcolor="#B0B0B0" ?>
6706 <entry namest="c1" nameend="c3">
6713 <classname>std::priority_queue</classname>
6716 <classname>Sequence</classname>
6719 <classname>std::vector</classname>
6725 <?dbhtml bgcolor="#B0B0B0" ?>
6726 <entry namest="c1" nameend="c3">
6733 <classname>std::priority_queue</classname>
6736 <classname>Sequence</classname>
6739 <classname>std::deque</classname>
6743 <!-- priority_queue 01 -->
6745 <?dbhtml bgcolor="#B0B0B0" ?>
6746 <entry namest="c1" nameend="c3">
6753 <classname>priority_queue</classname>
6756 <classname>Tag</classname>
6759 <classname>binary_heap_tag</classname>
6763 <!-- priority_queue 02 -->
6765 <?dbhtml bgcolor="#B0B0B0" ?>
6766 <entry namest="c1" nameend="c3">
6773 <classname>priority_queue</classname>
6776 <classname>Tag</classname>
6779 <classname>binomial_heap_tag</classname>
6783 <!-- priority_queue 03 -->
6785 <?dbhtml bgcolor="#B0B0B0" ?>
6786 <entry namest="c1" nameend="c3">
6793 <classname>priority_queue</classname>
6796 <classname>Tag</classname>
6799 <classname>rc_binomial_heap_tag</classname>
6803 <!-- priority_queue 04 -->
6805 <?dbhtml bgcolor="#B0B0B0" ?>
6806 <entry namest="c1" nameend="c3">
6813 <classname>priority_queue</classname>
6816 <classname>Tag</classname>
6819 <classname>thin_heap_tag</classname>
6824 <!-- priority_queue 05 -->
6826 <?dbhtml bgcolor="#B0B0B0" ?>
6827 <entry namest="c1" nameend="c3">
6834 <classname>priority_queue</classname>
6837 <classname>Tag</classname>
6840 <classname>pairing_heap_tag</classname>
6850 <para>The graphic below shows the results for the binary-heap
6851 based native priority queues and this library's pairing-heap
6852 priority_queue data structures.
6855 <!-- results graphic -->
6859 <imagedata align="center" format="PDF" scale="75"
6860 fileref="../images/pbds_pairing_priority_queue_text_push.pdf"/>
6863 <imagedata align="center" format="PNG" scale="100"
6864 fileref="../images/pbds_pairing_priority_queue_text_push.png"/>
6870 The abbreviated names in the legend of the graphic above are
6871 instantiated with the types in the following table.
6875 <informaltable frame="all">
6877 <tgroup cols="3" align="left" colsep="1" rowsep="1">
6878 <colspec colname="c1"/>
6879 <colspec colname="c2"/>
6880 <colspec colname="c3"/>
6883 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
6884 <entry><emphasis>Parameter</emphasis></entry>
6885 <entry><emphasis>Details</emphasis></entry>
6892 <?dbhtml bgcolor="#B0B0B0" ?>
6893 <entry namest="c1" nameend="c3">
6900 <classname>std::priority_queue</classname>
6903 <classname>Sequence</classname>
6906 <classname>std::vector</classname>
6912 <?dbhtml bgcolor="#B0B0B0" ?>
6913 <entry namest="c1" nameend="c3">
6920 <classname>std::priority_queue</classname>
6923 <classname>Sequence</classname>
6926 <classname>std::deque</classname>
6931 <!-- priority_queue 01 -->
6933 <?dbhtml bgcolor="#B0B0B0" ?>
6934 <entry namest="c1" nameend="c3">
6941 <classname>priority_queue</classname>
6944 <classname>Tag</classname>
6947 <classname>thin_heap_tag</classname>
6952 <!-- priority_queue 02 -->
6954 <?dbhtml bgcolor="#B0B0B0" ?>
6955 <entry namest="c1" nameend="c3">
6962 <classname>priority_queue</classname>
6965 <classname>Tag</classname>
6968 <classname>pairing_heap_tag</classname>
6979 <section xml:id="priority_queue.text_push.observations">
6984 <para>Pairing heaps (<classname>priority_queue</classname> with
6985 <classname>Tag</classname> = <classname>pairing_heap_tag</classname>)
6986 are the most suited for sequences of <function>push</function> and
6987 <function>pop</function> operations of non-primitive types (e.g.
6988 <classname>std::string</classname>s). (See Priority Queue
6989 Text <function>push</function> and <function>pop</function> Timing Test.) They are
6990 less constrained than binomial heaps, e.g., and since
6991 they are node-based, they outperform binary heaps. (See
6993 Queue Random Integer <function>push</function> Timing Test for the case
6994 of primitive types.)</para>
6996 <para>The standard's priority queues do not seem to perform well in
6997 this case: the <classname>std::vector</classname> implementation needs to
6998 perform a logarithmic sequence of string operations for each
6999 operation, and the deque implementation is possibly hampered by
7000 its need to manipulate a relatively-complex type (deques
7001 support a O(1) <function>push_front</function>, even though it is
7002 not used by <classname>std::priority_queue</classname>.)</para>
7007 <!-- 02 <a href="priority_queue_text_push_pop_timing_test"> -->
7008 <section xml:id="performance.priority_queue.text_push_pop">
7010 Text <function>push</function> and <function>pop</function>
7014 <section xml:id="priority_queue.text_push_pop.info">
7019 <para>This test inserts a number of values with keys from an
7020 arbitrary text ([ wickland96thirty ]) into
7021 a container using <classname>push</classname> , then removes them using
7022 <classname>pop</classname> . It measures the average time for <classname>push</classname>
7023 as a function of the number of values.</para>
7027 It uses the test file:
7028 <filename>performance/ext/pb_ds/priority_queue_text_push_pop_timing.cc</filename>
7031 <para>The test checks the effect of different underlying data
7037 <section xml:id="priority_queue.text_push_pop.results">
7042 <para>The two graphics below show the results for the native
7043 priority_queues and this library's priority_queues.
7046 <para>The graphic immediately below shows the results for the
7047 native priority_queue type instantiated with different underlying
7048 container types versus several different versions of library's
7052 <!-- results graphic -->
7056 <imagedata align="center" format="PDF" scale="75"
7057 fileref="../images/pbds_priority_queue_text_push_pop.pdf"/>
7060 <imagedata align="center" format="PNG" scale="100"
7061 fileref="../images/pbds_priority_queue_text_push_pop.png"/>
7067 The abbreviated names in the legend of the graphic above are
7068 instantiated with the types in the following table.
7072 <informaltable frame="all">
7074 <tgroup cols="3" align="left" colsep="1" rowsep="1">
7075 <colspec colname="c1"/>
7076 <colspec colname="c2"/>
7077 <colspec colname="c3"/>
7080 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
7081 <entry><emphasis>Parameter</emphasis></entry>
7082 <entry><emphasis>Details</emphasis></entry>
7090 <?dbhtml bgcolor="#B0B0B0" ?>
7091 <entry namest="c1" nameend="c3">
7098 <classname>std::priority_queue</classname>
7101 <classname>Sequence</classname>
7104 <classname>std::vector</classname>
7110 <?dbhtml bgcolor="#B0B0B0" ?>
7111 <entry namest="c1" nameend="c3">
7118 <classname>std::priority_queue</classname>
7121 <classname>Sequence</classname>
7124 <classname>std::deque</classname>
7129 <!-- priority_queue 01 -->
7131 <?dbhtml bgcolor="#B0B0B0" ?>
7132 <entry namest="c1" nameend="c3">
7139 <classname>priority_queue</classname>
7142 <classname>Tag</classname>
7145 <classname>binary_heap_tag</classname>
7149 <!-- priority_queue 02 -->
7151 <?dbhtml bgcolor="#B0B0B0" ?>
7152 <entry namest="c1" nameend="c3">
7159 <classname>priority_queue</classname>
7162 <classname>Tag</classname>
7165 <classname>binomial_heap_tag</classname>
7169 <!-- priority_queue 03 -->
7171 <?dbhtml bgcolor="#B0B0B0" ?>
7172 <entry namest="c1" nameend="c3">
7179 <classname>priority_queue</classname>
7182 <classname>Tag</classname>
7185 <classname>rc_binomial_heap_tag</classname>
7189 <!-- priority_queue 04 -->
7191 <?dbhtml bgcolor="#B0B0B0" ?>
7192 <entry namest="c1" nameend="c3">
7199 <classname>priority_queue</classname>
7202 <classname>Tag</classname>
7205 <classname>thin_heap_tag</classname>
7209 <!-- priority_queue 05 -->
7211 <?dbhtml bgcolor="#B0B0B0" ?>
7212 <entry namest="c1" nameend="c3">
7219 <classname>priority_queue</classname>
7222 <classname>Tag</classname>
7225 <classname>pairing_heap_tag</classname>
7235 <para>The graphic below shows the results for the native priority
7236 queues and this library's pairing-heap priority_queue data
7240 <!-- results graphic -->
7244 <imagedata align="center" format="PDF" scale="75"
7245 fileref="../images/pbds_pairing_priority_queue_text_push_pop.pdf"/>
7248 <imagedata align="center" format="PNG" scale="100"
7249 fileref="../images/pbds_pairing_priority_queue_text_push_pop.png"/>
7255 The abbreviated names in the legend of the graphic above are
7256 instantiated with the types in the following table.
7260 <informaltable frame="all">
7262 <tgroup cols="3" align="left" colsep="1" rowsep="1">
7263 <colspec colname="c1"/>
7264 <colspec colname="c2"/>
7265 <colspec colname="c3"/>
7268 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
7269 <entry><emphasis>Parameter</emphasis></entry>
7270 <entry><emphasis>Details</emphasis></entry>
7278 <?dbhtml bgcolor="#B0B0B0" ?>
7279 <entry namest="c1" nameend="c3">
7286 <classname>std::priority_queue</classname> adapting <classname>std::vector</classname>
7289 <classname>Sequence</classname>
7292 <classname>std::vector</classname>
7299 <?dbhtml bgcolor="#B0B0B0" ?>
7300 <entry namest="c1" nameend="c3">
7307 <classname>std::priority_queue</classname>
7310 <classname>Sequence</classname>
7313 <classname>std::deque</classname>
7318 <!-- priority_queue 01 -->
7320 <?dbhtml bgcolor="#B0B0B0" ?>
7321 <entry namest="c1" nameend="c3">
7328 <classname>priority_queue</classname>
7331 <classname>Tag</classname>
7334 <classname>pairing_heap_tag</classname>
7345 <section xml:id="priority_queue.text_push_pop.observations">
7350 <para>These results are very similar to Priority Queue Text
7351 <function>push</function> Timing Test. As stated there, pairing heaps
7352 (<classname>priority_queue</classname> with
7353 <classname>Tag</classname>
7354 = <classname>pairing_heap_tag</classname>) are most suited
7355 for <function>push</function> and <function>pop</function>
7356 sequences of non-primitive types such as strings. Observing these
7357 two tests, one can note that a pairing heap outperforms the others
7358 in terms of <function>push</function> operations, but equals
7359 binary heaps (<classname>priority_queue</classname> with
7360 <classname>Tag</classname>
7361 = <classname>binary_heap_tag</classname>) if the number
7362 of <function>push</function> and <function>pop</function>
7363 operations is equal. As the number of <function>pop</function>
7364 operations is at most equal to the number
7365 of <function>push</function> operations, pairing heaps are better
7366 in this case. See Priority Queue Random
7367 Integer <function>push</function> and <function>pop</function>
7368 Timing Test for a case which is different.</para>
7374 <!-- 03 <a href="priority_queue_random_int_push_timing_test"> -->
7375 <section xml:id="performance.priority_queue.int_push">
7377 Integer <function>push</function>
7381 <section xml:id="priority_queue.int_push.info">
7386 <para>This test inserts a number of values with integer keys
7387 into a container using <function>push</function>. It
7388 measures the average time for <function>push</function> as a
7389 function of the number of values.</para>
7392 It uses the test file:
7393 <filename>performance/ext/pb_ds/priority_queue_random_int_push_timing.cc</filename>
7396 <para>The test checks the effect of different underlying data
7402 <section xml:id="priority_queue.int_push.results">
7407 <para>The two graphics below show the results for the native
7408 priority_queues and this library's priority_queues.
7411 <para>The graphic immediately below shows the results for the
7412 native priority_queue type instantiated with different underlying
7413 container types versus several different versions of library's
7417 <!-- results graphic -->
7421 <imagedata align="center" format="PDF" scale="75"
7422 fileref="../images/pbds_priority_queue_int_push.pdf"/>
7425 <imagedata align="center" format="PNG" scale="100"
7426 fileref="../images/pbds_priority_queue_int_push.png"/>
7432 The abbreviated names in the legend of the graphic above are
7433 instantiated with the types in the following table.
7437 <informaltable frame="all">
7439 <tgroup cols="3" align="left" colsep="1" rowsep="1">
7440 <colspec colname="c1"/>
7441 <colspec colname="c2"/>
7442 <colspec colname="c3"/>
7445 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
7446 <entry><emphasis>Parameter</emphasis></entry>
7447 <entry><emphasis>Details</emphasis></entry>
7455 <?dbhtml bgcolor="#B0B0B0" ?>
7456 <entry namest="c1" nameend="c3">
7463 <classname>std::priority_queue</classname>
7466 <classname>Sequence</classname>
7469 <classname>std::vector</classname>
7475 <?dbhtml bgcolor="#B0B0B0" ?>
7476 <entry namest="c1" nameend="c3">
7483 <classname>std::priority_queue</classname>
7486 <classname>Sequence</classname>
7489 <classname>std::deque</classname>
7494 <!-- priority_queue 01 -->
7496 <?dbhtml bgcolor="#B0B0B0" ?>
7497 <entry namest="c1" nameend="c3">
7504 <classname>priority_queue</classname>
7507 <classname>Tag</classname>
7510 <classname>binary_heap_tag</classname>
7514 <!-- priority_queue 02 -->
7516 <?dbhtml bgcolor="#B0B0B0" ?>
7517 <entry namest="c1" nameend="c3">
7524 <classname>priority_queue</classname>
7527 <classname>Tag</classname>
7530 <classname>binomial_heap_tag</classname>
7534 <!-- priority_queue 03 -->
7536 <?dbhtml bgcolor="#B0B0B0" ?>
7537 <entry namest="c1" nameend="c3">
7544 <classname>priority_queue</classname>
7547 <classname>Tag</classname>
7550 <classname>rc_binomial_heap_tag</classname>
7554 <!-- priority_queue 04 -->
7556 <?dbhtml bgcolor="#B0B0B0" ?>
7557 <entry namest="c1" nameend="c3">
7564 <classname>priority_queue</classname>
7567 <classname>Tag</classname>
7570 <classname>thin_heap_tag</classname>
7574 <!-- priority_queue 05 -->
7576 <?dbhtml bgcolor="#B0B0B0" ?>
7577 <entry namest="c1" nameend="c3">
7584 <classname>priority_queue</classname>
7587 <classname>Tag</classname>
7590 <classname>pairing_heap_tag</classname>
7600 <para>The graphic below shows the results for the binary-heap
7601 based native priority queues and this library's
7602 priority_queue data structures.
7605 <!-- results graphic -->
7609 <imagedata align="center" format="PDF" scale="75"
7610 fileref="../images/pbds_binary_priority_queue_int_push.pdf"/>
7613 <imagedata align="center" format="PNG" scale="100"
7614 fileref="../images/pbds_binary_priority_queue_int_push.png"/>
7620 The abbreviated names in the legend of the graphic above are
7621 instantiated with the types in the following table.
7625 <informaltable frame="all">
7627 <tgroup cols="3" align="left" colsep="1" rowsep="1">
7628 <colspec colname="c1"/>
7629 <colspec colname="c2"/>
7630 <colspec colname="c3"/>
7633 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
7634 <entry><emphasis>Parameter</emphasis></entry>
7635 <entry><emphasis>Details</emphasis></entry>
7643 <?dbhtml bgcolor="#B0B0B0" ?>
7644 <entry namest="c1" nameend="c3">
7651 <classname>std::priority_queue</classname> adapting <classname>std::vector</classname>
7654 <classname>Sequence</classname>
7657 <classname>std::vector</classname>
7664 <?dbhtml bgcolor="#B0B0B0" ?>
7665 <entry namest="c1" nameend="c3">
7672 <classname>std::priority_queue</classname>
7675 <classname>Sequence</classname>
7678 <classname>std::deque</classname>
7683 <!-- priority_queue 01 -->
7685 <?dbhtml bgcolor="#B0B0B0" ?>
7686 <entry namest="c1" nameend="c3">
7693 <classname>priority_queue</classname>
7696 <classname>Tag</classname>
7699 <classname>binary_heap_tag</classname>
7710 <section xml:id="priority_queue.int_push.observations">
7716 <para>Binary heaps are the most suited for sequences of
7717 <function>push</function> and <function>pop</function> operations of primitive types
7718 (e.g. <type>int</type>s). They are less constrained
7719 than any other type, and since it is very efficient to store
7720 such types in arrays, they outperform even pairing heaps. (See
7722 Queue Text <function>push</function> Timing Test for the case of
7723 non-primitive types.)</para>
7727 <!-- 04 "priority_queue_random_int_push_pop_timing_test" -->
7728 <section xml:id="performance.priority_queue.int_push_pop">
7730 Integer <function>push</function>
7734 <section xml:id="priority_queue.int_push_pop.info">
7739 <para>This test inserts a number of values with integer keys
7740 into a container using <function>push</function> , then removes them
7741 using <function>pop</function> . It measures the average time for
7742 <function>push</function> and <function>pop</function> as a function
7743 of the number of values.</para>
7746 It uses the test file:
7747 <filename>performance/ext/pb_ds/priority_queue_random_int_push_pop_timing.cc</filename>
7750 <para>The test checks the effect of different underlying data
7756 <section xml:id="priority_queue.int_push_pop.results">
7761 <para>The graphic immediately below shows the results for the
7762 native priority_queue type instantiated with different underlying
7763 container types versus several different versions of library's
7767 <!-- results graphic -->
7771 <imagedata align="center" format="PDF" scale="75"
7772 fileref="../images/pbds_priority_queue_int_push_pop.pdf"/>
7775 <imagedata align="center" format="PNG" scale="100"
7776 fileref="../images/pbds_priority_queue_int_push_pop.png"/>
7782 The abbreviated names in the legend of the graphic above are
7783 instantiated with the types in the following table.
7787 <informaltable frame="all">
7789 <tgroup cols="3" align="left" colsep="1" rowsep="1">
7790 <colspec colname="c1"/>
7791 <colspec colname="c2"/>
7792 <colspec colname="c3"/>
7795 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
7796 <entry><emphasis>Parameter</emphasis></entry>
7797 <entry><emphasis>Details</emphasis></entry>
7805 <?dbhtml bgcolor="#B0B0B0" ?>
7806 <entry namest="c1" nameend="c3">
7813 <classname>std::priority_queue</classname>
7816 <classname>Sequence</classname>
7819 <classname>std::vector</classname>
7825 <?dbhtml bgcolor="#B0B0B0" ?>
7826 <entry namest="c1" nameend="c3">
7833 <classname>std::priority_queue</classname>
7836 <classname>Sequence</classname>
7839 <classname>std::deque</classname>
7844 <!-- priority_queue 01 -->
7846 <?dbhtml bgcolor="#B0B0B0" ?>
7847 <entry namest="c1" nameend="c3">
7854 <classname>priority_queue</classname>
7857 <classname>Tag</classname>
7860 <classname>binary_heap_tag</classname>
7864 <!-- priority_queue 02 -->
7866 <?dbhtml bgcolor="#B0B0B0" ?>
7867 <entry namest="c1" nameend="c3">
7874 <classname>priority_queue</classname>
7877 <classname>Tag</classname>
7880 <classname>binomial_heap_tag</classname>
7884 <!-- priority_queue 03 -->
7886 <?dbhtml bgcolor="#B0B0B0" ?>
7887 <entry namest="c1" nameend="c3">
7894 <classname>priority_queue</classname>
7897 <classname>Tag</classname>
7900 <classname>rc_binomial_heap_tag</classname>
7904 <!-- priority_queue 04 -->
7906 <?dbhtml bgcolor="#B0B0B0" ?>
7907 <entry namest="c1" nameend="c3">
7914 <classname>priority_queue</classname>
7917 <classname>Tag</classname>
7920 <classname>thin_heap_tag</classname>
7924 <!-- priority_queue 05 -->
7926 <?dbhtml bgcolor="#B0B0B0" ?>
7927 <entry namest="c1" nameend="c3">
7934 <classname>priority_queue</classname>
7937 <classname>Tag</classname>
7940 <classname>pairing_heap_tag</classname>
7952 <section xml:id="priority_queue.int_push_pop.observations">
7957 <para>Binary heaps are the most suited for sequences of
7958 <function>push</function> and <function>pop</function> operations of primitive types
7959 (e.g. <type>int</type>s). This is explained in
7961 Queue Random Int <function>push</function> Timing Test. (See Priority Queue
7962 Text <function>push</function> Timing Test for the case of primitive
7965 <para>At first glance it seems that the standard's vector-based
7966 priority queue is approximately on par with this
7967 library's corresponding priority queue. There are two
7968 differences however:</para>
7970 <listitem><para>The standard's priority queue does not downsize the underlying
7971 vector (or deque) as the priority queue becomes smaller
7973 Text <function>pop</function> Memory Use Test). It is therefore
7974 gaining some speed at the expense of space.</para></listitem>
7975 <listitem><para>From Priority Queue Random
7976 Integer <function>push</function> and <function>pop</function>
7977 Timing Test, it seems that the standard's priority queue is
7978 slower in terms of <function>push</function> operations. Since
7980 <function>pop</function> operations is at most that of <function>push</function>
7981 operations, the test here is the "best" for the standard's
7982 priority queue.</para></listitem>
7990 <!-- 05 <a href="priority_queue_text_pop_mem_usage_test"> -->
7991 <section xml:id="performance.priority_queue.text_pop">
7993 Text <function>pop</function> Memory Use
7997 <section xml:id="priority_queue.text_pop.info">
8003 <para>This test inserts a number of values with keys from an
8004 arbitrary text ([ wickland96thirty ]) into
8005 a container, then pops them until only one is left in the
8006 container. It measures the memory use as a function of the
8007 number of values pushed to the container.</para>
8009 It uses the test file:
8010 <filename>performance/ext/pb_ds/priority_queue_text_pop_mem_usage.cc</filename>
8013 <para>The test checks the effect of different underlying data
8019 <section xml:id="priority_queue.text_pop.results">
8024 <para>The graphic immediately below shows the results for the
8025 native priority_queue type instantiated with different underlying
8026 container types versus several different versions of library's
8030 <!-- results graphic -->
8034 <imagedata align="center" format="PDF" scale="75"
8035 fileref="../images/pbds_priority_queue_text_pop_mem.pdf"/>
8038 <imagedata align="center" format="PNG" scale="100"
8039 fileref="../images/pbds_priority_queue_text_pop_mem.png"/>
8045 The abbreviated names in the legend of the graphic above are
8046 instantiated with the types in the following table.
8050 <informaltable frame="all">
8052 <tgroup cols="3" align="left" colsep="1" rowsep="1">
8053 <colspec colname="c1"/>
8054 <colspec colname="c2"/>
8055 <colspec colname="c3"/>
8058 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
8059 <entry><emphasis>Parameter</emphasis></entry>
8060 <entry><emphasis>Details</emphasis></entry>
8068 <?dbhtml bgcolor="#B0B0B0" ?>
8069 <entry namest="c1" nameend="c3">
8076 <classname>std::priority_queue</classname>
8079 <classname>Sequence</classname>
8082 <classname>std::vector</classname>
8088 <?dbhtml bgcolor="#B0B0B0" ?>
8089 <entry namest="c1" nameend="c3">
8096 <classname>std::priority_queue</classname>
8099 <classname>Sequence</classname>
8102 <classname>std::deque</classname>
8107 <!-- priority_queue 01 -->
8109 <?dbhtml bgcolor="#B0B0B0" ?>
8110 <entry namest="c1" nameend="c3">
8117 <classname>priority_queue</classname>
8120 <classname>Tag</classname>
8123 <classname>binary_heap_tag</classname>
8127 <!-- priority_queue 02 -->
8129 <?dbhtml bgcolor="#B0B0B0" ?>
8130 <entry namest="c1" nameend="c3">
8137 <classname>priority_queue</classname>
8140 <classname>Tag</classname>
8143 <classname>binomial_heap_tag</classname>
8147 <!-- priority_queue 03 -->
8149 <?dbhtml bgcolor="#B0B0B0" ?>
8150 <entry namest="c1" nameend="c3">
8157 <classname>priority_queue</classname>
8160 <classname>Tag</classname>
8163 <classname>rc_binomial_heap_tag</classname>
8167 <!-- priority_queue 04 -->
8169 <?dbhtml bgcolor="#B0B0B0" ?>
8170 <entry namest="c1" nameend="c3">
8177 <classname>priority_queue</classname>
8180 <classname>Tag</classname>
8183 <classname>thin_heap_tag</classname>
8187 <!-- priority_queue 05 -->
8189 <?dbhtml bgcolor="#B0B0B0" ?>
8190 <entry namest="c1" nameend="c3">
8197 <classname>priority_queue</classname>
8200 <classname>Tag</classname>
8203 <classname>pairing_heap_tag</classname>
8215 <section xml:id="priority_queue.text_pop.observations">
8221 <para>The priority queue implementations (excluding the standard's) use
8222 memory proportionally to the number of values they hold:
8223 node-based implementations (e.g., a pairing heap) do so
8224 naturally; this library's binary heap de-allocates memory when
8225 a certain lower threshold is exceeded.</para>
8227 <para>Note from Priority Queue Text <function>push</function>
8228 and <function>pop</function> Timing Test and Priority Queue
8229 Random Integer <function>push</function>
8230 and <function>pop</function> Timing Test that this does not
8231 impede performance compared to the standard's priority
8233 <para>See Hash-Based Erase
8234 Memory Use Test for a similar phenomenon regarding priority
8239 <!-- 06 <a href="priority_queue_text_join_timing_test"> -->
8240 <section xml:id="performance.priority_queue.text_join">
8242 Text <function>join</function>
8246 <section xml:id="priority_queue.text_join.info">
8251 <para>This test inserts a number of values with keys from an
8252 arbitrary text ([ wickland96thirty ]) into
8253 two containers, then merges the containers. It uses
8254 <function>join</function> for this library's priority queues; for
8255 the standard's priority queues, it successively pops values from
8256 one container and pushes them into the other. The test measures
8257 the average time as a function of the number of values.</para>
8259 It uses the test file:
8260 <filename>performance/ext/pb_ds/priority_queue_text_join_timing.cc</filename>
8263 <para>The test checks the effect of different underlying data
8269 <section xml:id="priority_queue.text_join.results">
8274 <para>The graphic immediately below shows the results for the
8275 native priority_queue type instantiated with different underlying
8276 container types versus several different versions of library's
8280 <!-- results graphic -->
8284 <imagedata align="center" format="PDF" scale="75"
8285 fileref="../images/pbds_priority_queue_text_join.pdf"/>
8288 <imagedata align="center" format="PNG" scale="100"
8289 fileref="../images/pbds_priority_queue_text_join.png"/>
8295 The abbreviated names in the legend of the graphic above are
8296 instantiated with the types in the following table.
8300 <informaltable frame="all">
8302 <tgroup cols="3" align="left" colsep="1" rowsep="1">
8303 <colspec colname="c1"/>
8304 <colspec colname="c2"/>
8305 <colspec colname="c3"/>
8308 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
8309 <entry><emphasis>Parameter</emphasis></entry>
8310 <entry><emphasis>Details</emphasis></entry>
8318 <?dbhtml bgcolor="#B0B0B0" ?>
8319 <entry namest="c1" nameend="c3">
8326 <classname>std::priority_queue</classname>
8329 <classname>Sequence</classname>
8332 <classname>std::vector</classname>
8338 <?dbhtml bgcolor="#B0B0B0" ?>
8339 <entry namest="c1" nameend="c3">
8346 <classname>std::priority_queue</classname>
8349 <classname>Sequence</classname>
8352 <classname>std::deque</classname>
8357 <!-- priority_queue 01 -->
8359 <?dbhtml bgcolor="#B0B0B0" ?>
8360 <entry namest="c1" nameend="c3">
8367 <classname>priority_queue</classname>
8370 <classname>Tag</classname>
8373 <classname>binary_heap_tag</classname>
8377 <!-- priority_queue 02 -->
8379 <?dbhtml bgcolor="#B0B0B0" ?>
8380 <entry namest="c1" nameend="c3">
8387 <classname>priority_queue</classname>
8390 <classname>Tag</classname>
8393 <classname>binomial_heap_tag</classname>
8397 <!-- priority_queue 03 -->
8399 <?dbhtml bgcolor="#B0B0B0" ?>
8400 <entry namest="c1" nameend="c3">
8407 <classname>priority_queue</classname>
8410 <classname>Tag</classname>
8413 <classname>rc_binomial_heap_tag</classname>
8417 <!-- priority_queue 04 -->
8419 <?dbhtml bgcolor="#B0B0B0" ?>
8420 <entry namest="c1" nameend="c3">
8427 <classname>priority_queue</classname>
8430 <classname>Tag</classname>
8433 <classname>thin_heap_tag</classname>
8437 <!-- priority_queue 05 -->
8439 <?dbhtml bgcolor="#B0B0B0" ?>
8440 <entry namest="c1" nameend="c3">
8447 <classname>priority_queue</classname>
8450 <classname>Tag</classname>
8453 <classname>pairing_heap_tag</classname>
8465 <section xml:id="priority_queue.text_join.observations">
8470 <para>In this test the node-based heaps perform <function>join</function> in
8471 either logarithmic or constant time. The binary heap requires
8472 linear time, since the well-known heapify algorithm [clrs2001] is linear.</para>
8473 <para>It would be possible to apply the heapify algorithm to the
8474 standard containers, if they would support iteration (which they
8475 don't). Barring iterators, it is still somehow possible to perform
8476 linear-time merge on a <classname>std::vector</classname>-based
8477 standard priority queue, using <function>top()</function>
8478 and <function>size()</function> (since they are enough to expose
8479 the underlying array), but this is impossible for
8480 a <classname>std::deque</classname>-based standard priority queue.
8481 Without heapify, the cost is super-linear.</para>
8486 <!-- 07 <a href="priority_queue_text_push_timing_test"> -->
8487 <section xml:id="performance.priority_queue.text_modify_up">
8489 Text <function>modify</function> Up
8493 <section xml:id="priority_queue.text_modify_up.info">
8498 <para>This test inserts a number of values with keys from an
8499 arbitrary text ([ wickland96thirty ]) into
8500 into a container then modifies each one "up" (i.e., it
8501 makes it larger). It uses <function>modify</function> for this library's
8502 priority queues; for the standard's priority queues, it pops values
8503 from a container until it reaches the value that should be
8504 modified, then pushes values back in. It measures the average
8505 time for <function>modify</function> as a function of the number of
8509 It uses the test file:
8510 <filename>performance/ext/pb_ds/priority_queue_text_modify_up_timing.cc</filename>
8513 <para>The test checks the effect of different underlying data
8514 structures for graph algorithms settings. Note that making an
8515 arbitrary value larger (in the sense of the priority queue's
8516 comparison functor) corresponds to decrease-key in standard graph
8517 algorithms [clrs2001].
8522 <section xml:id="priority_queue.text_modify_up.results">
8527 <para>The two graphics below show the results for the native
8528 priority_queues and this library's priority_queues.
8531 <para>The graphic immediately below shows the results for the
8532 native priority_queue type instantiated with different underlying
8533 container types versus several different versions of library's
8537 <!-- results graphic -->
8541 <imagedata align="center" format="PDF" scale="75"
8542 fileref="../images/pbds_priority_queue_text_modify_up.pdf"/>
8545 <imagedata align="center" format="PNG" scale="100"
8546 fileref="../images/pbds_priority_queue_text_modify_up.png"/>
8552 The abbreviated names in the legend of the graphic above are
8553 instantiated with the types in the following table.
8557 <informaltable frame="all">
8559 <tgroup cols="3" align="left" colsep="1" rowsep="1">
8560 <colspec colname="c1"/>
8561 <colspec colname="c2"/>
8562 <colspec colname="c3"/>
8565 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
8566 <entry><emphasis>Parameter</emphasis></entry>
8567 <entry><emphasis>Details</emphasis></entry>
8575 <?dbhtml bgcolor="#B0B0B0" ?>
8576 <entry namest="c1" nameend="c3">
8583 <classname>std::priority_queue</classname>
8586 <classname>Sequence</classname>
8589 <classname>std::vector</classname>
8595 <?dbhtml bgcolor="#B0B0B0" ?>
8596 <entry namest="c1" nameend="c3">
8603 <classname>std::priority_queue</classname>
8606 <classname>Sequence</classname>
8609 <classname>std::deque</classname>
8613 <!-- priority_queue 01 -->
8615 <?dbhtml bgcolor="#B0B0B0" ?>
8616 <entry namest="c1" nameend="c3">
8623 <classname>priority_queue</classname>
8626 <classname>Tag</classname>
8629 <classname>binary_heap_tag</classname>
8633 <!-- priority_queue 02 -->
8635 <?dbhtml bgcolor="#B0B0B0" ?>
8636 <entry namest="c1" nameend="c3">
8643 <classname>priority_queue</classname>
8646 <classname>Tag</classname>
8649 <classname>binomial_heap_tag</classname>
8653 <!-- priority_queue 03 -->
8655 <?dbhtml bgcolor="#B0B0B0" ?>
8656 <entry namest="c1" nameend="c3">
8663 <classname>priority_queue</classname>
8666 <classname>Tag</classname>
8669 <classname>rc_binomial_heap_tag</classname>
8673 <!-- priority_queue 04 -->
8675 <?dbhtml bgcolor="#B0B0B0" ?>
8676 <entry namest="c1" nameend="c3">
8683 <classname>priority_queue</classname>
8686 <classname>Tag</classname>
8689 <classname>thin_heap_tag</classname>
8694 <!-- priority_queue 05 -->
8696 <?dbhtml bgcolor="#B0B0B0" ?>
8697 <entry namest="c1" nameend="c3">
8704 <classname>priority_queue</classname>
8707 <classname>Tag</classname>
8710 <classname>pairing_heap_tag</classname>
8720 <para>The graphic below shows the results for the
8721 native priority queues and this library's pairing and thin heap
8722 priority_queue data structures.
8725 <!-- results graphic -->
8729 <imagedata align="center" format="PDF" scale="75"
8730 fileref="../images/pbds_pairing_priority_queue_text_modify_up_thin.pdf"/>
8733 <imagedata align="center" format="PNG" scale="100"
8734 fileref="../images/pbds_pairing_priority_queue_text_modify_up_thin.png"/>
8740 The abbreviated names in the legend of the graphic above are
8741 instantiated with the types in the following table.
8745 <informaltable frame="all">
8747 <tgroup cols="3" align="left" colsep="1" rowsep="1">
8748 <colspec colname="c1"/>
8749 <colspec colname="c2"/>
8750 <colspec colname="c3"/>
8753 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
8754 <entry><emphasis>Parameter</emphasis></entry>
8755 <entry><emphasis>Details</emphasis></entry>
8761 <!-- priority_queue 01 -->
8763 <?dbhtml bgcolor="#B0B0B0" ?>
8764 <entry namest="c1" nameend="c3">
8771 <classname>priority_queue</classname>
8774 <classname>Tag</classname>
8777 <classname>thin_heap_tag</classname>
8782 <!-- priority_queue 02 -->
8784 <?dbhtml bgcolor="#B0B0B0" ?>
8785 <entry namest="c1" nameend="c3">
8792 <classname>priority_queue</classname>
8795 <classname>Tag</classname>
8798 <classname>pairing_heap_tag</classname>
8809 <section xml:id="priority_queue.text_modify_up.observations">
8814 <para>As noted above, increasing an arbitrary value (in the sense of
8815 the priority queue's comparison functor) is very common in
8816 graph-related algorithms. In this case, a thin heap
8817 (<classname>priority_queue</classname> with
8818 <classname>Tag</classname> = <classname>thin_heap_tag</classname>)
8819 outperforms a pairing heap (<classname>priority_queue</classname> with
8820 <classname>Tag</classname> = <classname>pairing_heap_tag</classname>).
8821 Conversely, Priority Queue Text
8822 <function>push</function> Timing Test, Priority Queue
8823 Text <function>push</function> and <function>pop</function> Timing Test, Priority
8824 Queue Random Integer <function>push</function> Timing Test, and
8826 Queue Random Integer <function>push</function> and <function>pop</function> Timing
8827 Test show that the situation is reversed for other
8828 operations. It is not clear when to prefer one of these two
8829 different types.</para>
8831 <para>In this test this library's binary heaps
8832 effectively perform modify in linear time. As explained in
8833 Priority Queue Design::Traits, given a valid point-type iterator,
8834 a binary heap can perform
8835 <function>modify</function> logarithmically. The problem is that binary
8836 heaps invalidate their find iterators with each modifying
8837 operation, and so the only way to obtain a valid point-type
8838 iterator is to iterate using a range-type iterator until
8839 finding the appropriate value, then use the range-type iterator
8840 for the <function>modify</function> operation.</para>
8841 <para>The explanation for the standard's priority queues' performance
8842 is similar to that in Priority Queue Text
8843 <function>join</function> Timing Test.</para>
8849 <!-- 08 <a href="priority_queue_text_modify_down_timing_test"> -->
8851 <section xml:id="performance.priority_queue.text_modify_down">
8853 Text <function>modify</function> Down
8857 <section xml:id="priority_queue.text_modify_down.info">
8862 <para>This test inserts a number of values with keys from an
8863 arbitrary text ([ wickland96thirty ]) into
8864 into a container then modifies each one "down" (i.e., it
8865 makes it smaller). It uses <function>modify</function> for this library's
8866 priority queues; for the standard's priority queues, it pops values
8867 from a container until it reaches the value that should be
8868 modified, then pushes values back in. It measures the average
8869 time for <function>modify</function> as a function of the number of
8873 It uses the test file:
8874 <filename>performance/ext/pb_ds/priority_queue_text_modify_down_timing.cc</filename>
8877 <para>The main purpose of this test is to contrast Priority Queue
8878 Text <classname>modify</classname> Up Timing Test.</para>
8882 <section xml:id="priority_queue.text_modify_down.results">
8887 <para>The two graphics below show the results for the native
8888 priority_queues and this library's priority_queues.
8891 <para>The graphic immediately below shows the results for the
8892 native priority_queue type instantiated with different underlying
8893 container types versus several different versions of library's
8897 <!-- results graphic -->
8901 <imagedata align="center" format="PDF" scale="75"
8902 fileref="../images/pbds_priority_queue_text_modify_down.pdf"/>
8905 <imagedata align="center" format="PNG" scale="100"
8906 fileref="../images/pbds_priority_queue_text_modify_down.png"/>
8912 The abbreviated names in the legend of the graphic above are
8913 instantiated with the types in the following table.
8917 <informaltable frame="all">
8919 <tgroup cols="3" align="left" colsep="1" rowsep="1">
8920 <colspec colname="c1"/>
8921 <colspec colname="c2"/>
8922 <colspec colname="c3"/>
8925 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
8926 <entry><emphasis>Parameter</emphasis></entry>
8927 <entry><emphasis>Details</emphasis></entry>
8935 <?dbhtml bgcolor="#B0B0B0" ?>
8936 <entry namest="c1" nameend="c3">
8943 <classname>std::priority_queue</classname>
8946 <classname>Sequence</classname>
8949 <classname>std::vector</classname>
8955 <?dbhtml bgcolor="#B0B0B0" ?>
8956 <entry namest="c1" nameend="c3">
8963 <classname>std::priority_queue</classname>
8966 <classname>Sequence</classname>
8969 <classname>std::deque</classname>
8973 <!-- priority_queue 01 -->
8975 <?dbhtml bgcolor="#B0B0B0" ?>
8976 <entry namest="c1" nameend="c3">
8983 <classname>priority_queue</classname>
8986 <classname>Tag</classname>
8989 <classname>binary_heap_tag</classname>
8993 <!-- priority_queue 02 -->
8995 <?dbhtml bgcolor="#B0B0B0" ?>
8996 <entry namest="c1" nameend="c3">
9003 <classname>priority_queue</classname>
9006 <classname>Tag</classname>
9009 <classname>binomial_heap_tag</classname>
9013 <!-- priority_queue 03 -->
9015 <?dbhtml bgcolor="#B0B0B0" ?>
9016 <entry namest="c1" nameend="c3">
9023 <classname>priority_queue</classname>
9026 <classname>Tag</classname>
9029 <classname>rc_binomial_heap_tag</classname>
9033 <!-- priority_queue 04 -->
9035 <?dbhtml bgcolor="#B0B0B0" ?>
9036 <entry namest="c1" nameend="c3">
9043 <classname>priority_queue</classname>
9046 <classname>Tag</classname>
9049 <classname>thin_heap_tag</classname>
9054 <!-- priority_queue 05 -->
9056 <?dbhtml bgcolor="#B0B0B0" ?>
9057 <entry namest="c1" nameend="c3">
9064 <classname>priority_queue</classname>
9067 <classname>Tag</classname>
9070 <classname>pairing_heap_tag</classname>
9080 <para>The graphic below shows the results for the
9081 native priority queues and this library's pairing and thin heap
9082 priority_queue data structures.
9085 <!-- results graphic -->
9089 <imagedata align="center" format="PDF" scale="75"
9090 fileref="../images/pbds_pairing_priority_queue_text_modify_down_thin.pdf"/>
9093 <imagedata align="center" format="PNG" scale="100"
9094 fileref="../images/pbds_pairing_priority_queue_text_modify_down_thin.png"/>
9100 The abbreviated names in the legend of the graphic above are
9101 instantiated with the types in the following table.
9105 <informaltable frame="all">
9107 <tgroup cols="3" align="left" colsep="1" rowsep="1">
9108 <colspec colname="c1"/>
9109 <colspec colname="c2"/>
9110 <colspec colname="c3"/>
9113 <entry><emphasis>Name/Instantiating Type</emphasis></entry>
9114 <entry><emphasis>Parameter</emphasis></entry>
9115 <entry><emphasis>Details</emphasis></entry>
9121 <!-- priority_queue 01 -->
9123 <?dbhtml bgcolor="#B0B0B0" ?>
9124 <entry namest="c1" nameend="c3">
9131 <classname>priority_queue</classname>
9134 <classname>Tag</classname>
9137 <classname>thin_heap_tag</classname>
9142 <!-- priority_queue 02 -->
9144 <?dbhtml bgcolor="#B0B0B0" ?>
9145 <entry namest="c1" nameend="c3">
9152 <classname>priority_queue</classname>
9155 <classname>Tag</classname>
9158 <classname>pairing_heap_tag</classname>
9169 <section xml:id="priority_queue.text_modify_down.observations">
9174 <para>Most points in these results are similar to Priority Queue
9175 Text <function>modify</function> Up Timing Test.</para>
9177 <para>It is interesting to note, however, that as opposed to that
9178 test, a thin heap (<classname>priority_queue</classname> with
9179 <classname>Tag</classname> = <classname>thin_heap_tag</classname>) is
9180 outperformed by a pairing heap (<classname>priority_queue</classname> with
9181 <classname>Tag</classname> = <classname>pairing_heap_tag</classname>).
9182 In this case, both heaps essentially perform an <function>erase</function>
9183 operation followed by a <function>push</function> operation. As the other
9184 tests show, a pairing heap is usually far more efficient than a
9185 thin heap, so this is not surprising.</para>
9186 <para>Most algorithms that involve priority queues increase values
9187 (in the sense of the priority queue's comparison functor), and
9189 Text <classname>modify</classname> Up Timing Test - is more interesting
9190 than this test.</para>
9195 </section> <!-- priority_queue -->
9197 <section xml:id="pbds.test.performance.observations">
9198 <info><title>Observations</title></info>
9200 <section xml:id="observations.associative">
9201 <info><title>Associative</title></info>
9203 <section xml:id="observations.associative.underlying">
9205 Underlying Data-Structure Families
9208 <para>In general, hash-based containers have better timing performance
9209 than containers based on different underlying-data structures. The
9210 main reason to choose a tree-based or trie-based container is if a
9211 byproduct of the tree-like structure is required: either
9212 order-preservation, or the ability to utilize node invariants. If
9213 memory-use is the major factor, an ordered-vector tree gives
9214 optimal results (albeit with high modificiation costs), and a
9215 list-based container gives reasonable results.</para>
9219 <section xml:id="observations.associative.hash">
9221 Hash-Based Containers
9224 <para>Hash-based containers are typically either collision
9225 chaining or probing. Collision-chaining
9226 containers are more flexible internally, and so offer better
9227 timing performance. Probing containers, if used for simple
9228 value-types, manage memory more efficiently (they perform far
9229 fewer allocation-related calls). In general, therefore, a
9230 collision-chaining table should be used. A probing container,
9231 conversely, might be used efficiently for operations such as
9232 eliminating duplicates in a sequence, or counting the number of
9233 occurrences within a sequence. Probing containers might be more
9234 useful also in multithreaded applications where each thread
9235 manipulates a hash-based container: in the standard, allocators have
9236 class-wise semantics (see [meyers96more] - Item 10); a
9237 probing container might incur less contention in this case.</para>
9240 <section xml:id="observations.associative.hash_policies">
9245 <para>In hash-based containers, the range-hashing scheme seems to
9246 affect performance more than other considerations. In most
9247 settings, a mask-based scheme works well (or can be made to
9248 work well). If the key-distribution can be estimated a-priori,
9249 a simple hash function can produce nearly uniform hash-value
9250 distribution. In many other cases (e.g., text hashing,
9251 floating-point hashing), the hash function is powerful enough
9252 to generate hash values with good uniformity properties
9254 a modulo-based scheme, taking into account all bits of the hash
9255 value, appears to overlap the hash function in its effort.</para>
9256 <para>The range-hashing scheme determines many of the other
9257 policies. A mask-based scheme works
9258 well with an exponential-size policy; for
9259 probing-based containers, it goes well with a linear-probe
9261 <para>An orthogonal consideration is the trigger policy. This
9262 presents difficult tradeoffs. E.g., different load
9263 factors in a load-check trigger policy yield a
9264 space/amortized-cost tradeoff.</para>
9267 <section xml:id="observations.associative.branch">
9269 Branch-Based Containers
9271 <para>In general, there are several families of tree-based
9272 underlying data structures: balanced node-based trees
9273 (e.g., red-black or AVL trees), high-probability
9274 balanced node-based trees (e.g., random treaps or
9275 skip-lists), competitive node-based trees (e.g., splay
9276 trees), vector-based "trees", and tries. (Additionally, there
9277 are disk-residing or network-residing trees, such as B-Trees
9278 and their numerous variants. An interface for this would have
9279 to deal with the execution model and ACID guarantees; this is
9280 out of the scope of this library.) Following are some
9281 observations on their application to different settings.</para>
9283 <para>Of the balanced node-based trees, this library includes a
9284 red-black tree, as does standard (in
9285 practice). This type of tree is the "workhorse" of tree-based
9286 containers: it offers both reasonable modification and
9287 reasonable lookup time. Unfortunately, this data structure
9288 stores a huge amount of metadata. Each node must contain,
9289 besides a value, three pointers and a boolean. This type might
9290 be avoided if space is at a premium [austern00noset].</para>
9291 <para>High-probability balanced node-based trees suffer the
9292 drawbacks of deterministic balanced trees. Although they are
9293 fascinating data structures, preliminary tests with them showed
9294 their performance was worse than red-black trees. The library
9295 does not contain any such trees, therefore.</para>
9296 <para>Competitive node-based trees have two drawbacks. They are
9297 usually somewhat unbalanced, and they perform a large number of
9298 comparisons. Balanced trees perform one comparison per each
9299 node they encounter on a search path; a splay tree performs two
9300 comparisons. If the keys are complex objects, e.g.,
9301 <classname>std::string</classname>, this can increase the running time.
9302 Conversely, such trees do well when there is much locality of
9303 reference. It is difficult to determine in which case to prefer
9304 such trees over balanced trees. This library includes a splay
9306 <para>Ordered-vector trees use very little space
9308 They do not have any other advantages (at least in this
9309 implementation).</para>
9310 <para>Large-fan-out PATRICIA tries have excellent lookup
9311 performance, but they do so through maintaining, for each node,
9312 a miniature "hash-table". Their space efficiency is low, and
9313 their modification performance is bad. These tries might be
9314 used for semi-static settings, where order preservation is
9315 important. Alternatively, red-black trees cross-referenced with
9316 hash tables can be used. [okasaki98mereable]
9317 discusses small-fan-out PATRICIA tries for integers, but the
9318 cited results seem to indicate that the amortized cost of
9319 maintaining such trees is higher than that of balanced trees.
9320 Moderate-fan-out trees might be useful for sequences where each
9321 element has a limited number of choices, e.g., DNA
9325 <section xml:id="observations.associative.mapping_semantics">
9329 <para>Different mapping semantics were discussed in the introduction and design sections.Here
9330 the focus will be on the case where a keys can be composed into
9331 primary keys and secondary keys. (In the case where some keys
9332 are completely identical, it is trivial that one should use an
9333 associative container mapping values to size types.) In this
9334 case there are (at least) five possibilities:</para>
9336 <listitem><para>Use an associative container that allows equivalent-key
9337 values (such as <classname>std::multimap</classname>)</para></listitem>
9338 <listitem><para>Use a unique-key value associative container that maps
9339 each primary key to some complex associative container of
9340 secondary keys, say a tree-based or hash-based container.
9342 <listitem><para>Use a unique-key value associative container that maps
9343 each primary key to some simple associative container of
9344 secondary keys, say a list-based container.</para></listitem>
9345 <listitem><para>Use a unique-key value associative container that maps
9346 each primary key to some non-associative container
9347 (e.g., <classname>std::vector</classname>)</para></listitem>
9348 <listitem><para>Use a unique-key value associative container that takes
9349 into account both primary and secondary keys.</para></listitem>
9351 <para>Stated simply: there is a simple answer for this. (Excluding
9352 option 1, which should be avoided in all cases).</para>
9353 <para>If the expected ratio of secondary keys to primary keys is
9354 small, then 3 and 4 seem reasonable. Both types of secondary
9355 containers are relatively lightweight (in terms of memory use
9356 and construction time), and so creating an entire container
9357 object for each primary key is not too expensive. Option 4
9358 might be preferable to option 3 if changing the secondary key
9359 of some primary key is frequent - one cannot modify an
9360 associative container's key, and the only possibility,
9361 therefore, is erasing the secondary key and inserting another
9362 one instead; a non-associative container, conversely, can
9363 support in-place modification. The actual cost of erasing a
9364 secondary key and inserting another one depends also on the
9365 allocator used for secondary associative-containers (The tests
9366 above used the standard allocator, but in practice one might
9367 choose to use, e.g., [boost_pool]). Option 2 is
9368 definitely an overkill in this case. Option 1 loses out either
9369 immediately (when there is one secondary key per primary key)
9370 or almost immediately after that. Option 5 has the same
9371 drawbacks as option 2, but it has the additional drawback that
9372 finding all values whose primary key is equivalent to some key,
9373 might be linear in the total number of values stored (for
9374 example, if using a hash-based container).</para>
9375 <para>If the expected ratio of secondary keys to primary keys is
9376 large, then the answer is more complicated. It depends on the
9377 distribution of secondary keys to primary keys, the
9378 distribution of accesses according to primary keys, and the
9379 types of operations most frequent.</para>
9380 <para>To be more precise, assume there are m primary keys,
9381 primary key i is mapped to n<subscript>i</subscript>
9382 secondary keys, and each primary key is mapped, on average, to
9383 n secondary keys (i.e.,
9384 E(n<subscript>i</subscript>) = n).</para>
9385 <para>Suppose one wants to find a specific pair of primary and
9386 secondary keys. Using 1 with a tree based container
9387 (<classname>std::multimap</classname>), the expected cost is
9388 E(Θ(log(m) + n<subscript>i</subscript>)) = Θ(log(m) +
9389 n); using 1 with a hash-based container
9390 (<classname>std::tr1::unordered_multimap</classname>), the expected cost is
9391 Θ(n). Using 2 with a primary hash-based container
9392 and secondary hash-based containers, the expected cost is
9393 O(1); using 2 with a primary tree-based container and
9394 secondary tree-based containers, the expected cost is (using
9395 the Jensen inequality [motwani95random])
9396 E(O(log(m) + log(n<subscript>i</subscript>)) = O(log(m)) +
9397 E(O(log(n<subscript>i</subscript>)) = O(log(m)) + O(log(n)),
9398 assuming that primary keys are accessed equiprobably. 3 and 4
9399 are similar to 1, but with lower constants. Using 5 with a
9400 hash-based container, the expected cost is O(1); using 5
9401 with a tree based container, the cost is
9402 E(Θ(log(mn))) = Θ(log(m) +
9404 <para>Suppose one needs the values whose primary key matches some
9405 given key. Using 1 with a hash-based container, the expected
9406 cost is Θ(n), but the values will not be ordered
9407 by secondary keys (which may or may not be required); using 1
9408 with a tree-based container, the expected cost is
9409 Θ(log(m) + n), but with high constants; again the
9410 values will not be ordered by secondary keys. 2, 3, and 4 are
9411 similar to 1, but typically with lower constants (and,
9412 additionally, if one uses a tree-based container for secondary
9413 keys, they will be ordered). Using 5 with a hash-based
9414 container, the cost is Θ(mn).</para>
9415 <para>Suppose one wants to assign to a primary key all secondary
9416 keys assigned to a different primary key. Using 1 with a
9417 hash-based container, the expected cost is Θ(n),
9418 but with very high constants; using 1 with a tree-based
9419 container, the cost is Θ(nlog(mn)). Using 2, 3,
9420 and 4, the expected cost is Θ(n), but typically
9421 with far lower costs than 1. 5 is similar to 1.</para>
9428 <section xml:id="observations.priority_queue">
9429 <info><title>Priority_Queue</title></info>
9431 <section xml:id="observations.priority_queue.complexity">
9432 <info><title>Complexity</title></info>
9434 <para>The following table shows the complexities of the different
9435 underlying data structures in terms of orders of growth. It is
9436 interesting to note that this table implies something about the
9437 constants of the operations as well (see Amortized <function>push</function>
9438 and <function>pop</function> operations).</para>
9440 <informaltable frame="all">
9442 <tgroup cols="6" align="left" colsep="1" rowsep="1">
9443 <colspec colname="c1"/>
9444 <colspec colname="c2"/>
9445 <colspec colname="c3"/>
9446 <colspec colname="c4"/>
9447 <colspec colname="c5"/>
9448 <colspec colname="c6"/>
9452 <entry><emphasis><function>push</function></emphasis></entry>
9453 <entry><emphasis><function>pop</function></emphasis></entry>
9454 <entry><emphasis><function>modify</function></emphasis></entry>
9455 <entry><emphasis><function>erase</function></emphasis></entry>
9456 <entry><emphasis><function>join</function></emphasis></entry>
9464 <classname>std::priority_queue</classname>
9475 <subscript>[std note 1]</subscript>
9479 <subscript>[std note 2]</subscript>
9483 <subscript>[std note 1]</subscript>
9488 <classname>priority_queue</classname>
9489 <<classname>Tag</classname> =
9490 <classname>pairing_heap_tag</classname>>
9513 <classname>priority_queue</classname>
9514 <<classname>Tag</classname> =
9515 <classname>binary_heap_tag</classname>>
9537 <classname>priority_queue</classname>
9538 <<classname>Tag</classname> =
9539 <classname>binomial_heap_tag</classname>>
9560 <classname>priority_queue</classname>
9561 <<classname>Tag</classname> =
9562 <classname>rc_binomial_heap_tag</classname>>
9582 <classname>priority_queue</classname><<classname>Tag</classname> =
9583 <classname>thin_heap_tag</classname>>
9595 or Θ(log(n)) amortized
9596 <subscript>[thin_heap_note]</subscript>
9611 <para>[std note 1] This
9612 is not a property of the algorithm, but rather due to the fact
9613 that the standard's priority queue implementation does not support
9614 iterators (and consequently the ability to access a specific
9615 value inside it). If the priority queue is adapting an
9616 <classname>std::vector</classname>, then it is still possible to reduce this
9617 to Θ(n) by adapting over the standard's adapter and
9618 using the fact that <function>top</function> returns a reference to the
9619 first value; if, however, it is adapting an
9620 <classname>std::deque</classname>, then this is impossible.</para>
9622 <para>[std note 2] As
9623 with [std note 1], this is not a
9624 property of the algorithm, but rather the standard's implementation.
9625 Again, if the priority queue is adapting an
9626 <classname>std::vector</classname> then it is possible to reduce this to
9627 Θ(n), but with a very high constant (one must call
9628 <function>std::make_heap</function> which is an expensive linear
9629 operation); if the priority queue is adapting an
9630 <classname>std::deque</classname>, then this is impossible.</para>
9632 <para>[thin_heap_note] A thin heap has
9633 Θ(log(n)) worst case <function>modify</function> time
9634 always, but the amortized time depends on the nature of the
9635 operation: I) if the operation increases the key (in the sense
9636 of the priority queue's comparison functor), then the amortized
9637 time is O(1), but if II) it decreases it, then the
9638 amortized time is the same as the worst case time. Note that
9639 for most algorithms, I) is important and II) is not.</para>
9643 <section xml:id="observations.priority_queue.amortized_ops">
9645 Amortized <function>push</function>
9646 and <function>pop</function> operations
9650 <para>In many cases, a priority queue is needed primarily for
9651 sequences of <function>push</function> and <function>pop</function> operations. All of
9652 the underlying data structures have the same amortized
9653 logarithmic complexity, but they differ in terms of
9655 <para>The table above shows that the different data structures are
9656 "constrained" in some respects. In general, if a data structure
9657 has lower worst-case complexity than another, then it will
9658 perform slower in the amortized sense. Thus, for example a
9659 redundant-counter binomial heap (<classname>priority_queue</classname> with
9660 <classname>Tag</classname> = <classname>rc_binomial_heap_tag</classname>)
9661 has lower worst-case <function>push</function> performance than a binomial
9662 heap (<classname>priority_queue</classname>
9663 with <classname>Tag</classname> = <classname>binomial_heap_tag</classname>),
9664 and so its amortized <function>push</function> performance is slower in
9665 terms of constants.</para>
9666 <para>As the table shows, the "least constrained" underlying
9667 data structures are binary heaps and pairing heaps.
9668 Consequently, it is not surprising that they perform best in
9669 terms of amortized constants.</para>
9671 <listitem><para>Pairing heaps seem to perform best for non-primitive
9672 types (e.g., <classname>std::string</classname>s), as shown by
9674 Queue Text <function>push</function> Timing Test and Priority
9675 Queue Text <function>push</function> and <function>pop</function> Timing
9676 Test</para></listitem>
9677 <listitem><para>binary heaps seem to perform best for primitive types
9678 (e.g., <type>int</type>s), as shown by Priority
9679 Queue Random Integer <function>push</function> Timing Test and
9681 Queue Random Integer <function>push</function> and <function>pop</function> Timing
9682 Test.</para></listitem>
9687 <section xml:id="observations.priority_queue.graphs">
9692 <para>In some graph algorithms, a decrease-key operation is
9693 required [clrs2001];
9694 this operation is identical to <function>modify</function> if a value is
9695 increased (in the sense of the priority queue's comparison
9696 functor). The table above and Priority Queue
9697 Text <function>modify</function> Up Timing Test show that a thin heap
9698 (<classname>priority_queue</classname> with
9699 <classname>Tag</classname> = <classname>thin_heap_tag</classname>)
9700 outperforms a pairing heap (<classname>priority_queue</classname> with
9701 <classname>Tag</classname> = <classname>Tag</classname> = <classname>pairing_heap_tag</classname>),
9702 but the rest of the tests show otherwise.</para>
9704 <para>This makes it difficult to decide which implementation to use in
9705 this case. Dijkstra's shortest-path algorithm, for example, requires
9706 Θ(n) <function>push</function> and <function>pop</function> operations
9707 (in the number of vertices), but O(n<superscript>2</superscript>)
9708 <function>modify</function> operations, which can be in practice Θ(n)
9709 as well. It is difficult to find an a-priori characterization of
9710 graphs in which the actual number of <function>modify</function>
9711 operations will dwarf the number of <function>push</function> and
9712 <function>pop</function> operations.</para>
9716 </section> <!-- priority_queue -->
9721 </section> <!-- performance -->