<section xmlns="http://docbook.org/ns/docbook" version="5.0" | |
xml:id="pbds.test" xreflabel="Test"> | |
<info><title>Testing</title></info> | |
<?dbhtml filename="policy_based_data_structures_test.html"?> | |
<!-- S01 regression --> | |
<section xml:id="pbds.test.regression"> | |
<info><title>Regression</title></info> | |
<para>The library contains a single comprehensive regression test. | |
For a given container type in this library, the test creates | |
an object of the container type and an object of the | |
corresponding standard type (e.g., <classname>std::set</classname>). It | |
then performs a random sequence of methods with random | |
arguments (e.g., inserts, erases, and so forth) on both | |
objects. At each operation, the test checks the return value of | |
the method, and optionally both compares this library's | |
object with the standard's object as well as performing other | |
consistency checks on this library's object (e.g., | |
order preservation, when applicable, or node invariants, when | |
applicable).</para> | |
<para>Additionally, the test integrally checks exception safety | |
and resource leaks. This is done as follows. A special | |
allocator type, written for the purpose of the test, both | |
randomly throws an exceptions when allocations are performed, | |
and tracks allocations and de-allocations. The exceptions thrown | |
at allocations simulate memory-allocation failures; the | |
tracking mechanism checks for memory-related bugs (e.g., | |
resource leaks and multiple de-allocations). Both | |
this library's containers and the containers' value-types are | |
configured to use this allocator.</para> | |
<para>For granularity, the test is split into the | |
several sources, each checking only some containers.</para> | |
<para>For more details, consult the files in | |
<filename class="directory">testsuite/ext/pb_ds/regression</filename>. | |
</para> | |
</section> | |
<!-- S02 performance --> | |
<section xml:id="pbds.test.performance"> | |
<info><title>Performance</title></info> | |
<section xml:id="performance.hash"> | |
<info><title>Hash-Based</title></info> | |
<para></para> | |
<!-- 01 <a href="hash_text_find_find_timing_test"> --> | |
<section xml:id="performance.hash.text_find"> | |
<info><title> | |
Text <function>find</function> | |
</title></info> | |
<para></para> | |
<section xml:id="hash.text_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para> | |
This test inserts a number of values with keys from an | |
arbitrary text (<xref | |
linkend="biblio.wickland96thirty"/>) into a container, | |
then performs a series of finds using | |
<function>find</function> . It measures the average | |
time for <function>find</function> as a function of | |
the number of values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/text_find_timing_test.cc</filename> | |
</para> | |
<para> | |
And uses the data file: | |
<filename>filethirty_years_among_the_dead_preproc.txt</filename> | |
</para> | |
<para>The test checks the effect of different range-hashing | |
functions, trigger policies, and cache-hashing policies. | |
</para> | |
</section> | |
<section xml:id="hash.text_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic below show the results for the native | |
and collision-chaining hash types the function | |
applied being a text find timing test using | |
<function>find</function>. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_hash_text_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_hash_text_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_sth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname> | |
cc_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 04 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.text_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>In this setting, the range-hashing scheme affects performance | |
more than other policies. As the results show, containers using | |
mod-based range-hashing (including the native hash-based container, | |
which is currently hard-wired to this scheme) have lower performance | |
than those using mask-based range-hashing. A modulo-based | |
range-hashing scheme's main benefit is that it takes into account | |
all hash-value bits. Standard string hash-functions are designed to | |
create hash values that are nearly-uniform as is (<xref | |
linkend="biblio.knuth98sorting"/>).</para> | |
<para>Trigger policies, i.e. the load-checks constants, affect | |
performance to a lesser extent.</para> | |
<para>Perhaps surprisingly, storing the hash value alongside each | |
entry affects performance only marginally, at least in this | |
library's implementation. (Unfortunately, it was not possible to run | |
the tests with <classname>std::tr1::unordered_map</classname> 's | |
<classname>cache_hash_code = true</classname> , as it appeared to | |
malfuntion.)</para> | |
</section> | |
</section> | |
<!-- 02 <a href="hash_int_find_timing_test"> --> | |
<section xml:id="performance.hash.int_find"> | |
<info><title> | |
Integer <function>find</function> | |
</title></info> | |
<para></para> | |
<section xml:id="hash.int_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with uniform | |
integer keys into a container, then performs a series of finds | |
using <function>find</function>. It measures the average time | |
for <function>find</function> as a function of the number of values | |
inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/random_int_find_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different underlying | |
hash-tables, | |
range-hashing functions, and trigger policies.</para> | |
</section> | |
<section xml:id="hash.int_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para> | |
There are two sets of results for this type, one for | |
collision-chaining hashes, and one for general-probe hashes. | |
</para> | |
<para>The first graphic below shows the results for the native and | |
collision-chaining hash types. The function applied being a random | |
integer timing test using <function>find</function>. | |
</para> | |
<!-- results graphic 01 --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_cc_hash_int_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_cc_hash_int_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname> | |
cc_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 04 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
<para> | |
</para> | |
<para> | |
</para> | |
<para>And the second graphic shows the results for the native and | |
general-probe hash types. The function applied being a random | |
integer timing test using <function>find</function>. | |
</para> | |
<!-- results graphic 02 --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_gp_hash_int_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_gp_hash_int_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mod_quadp_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname>gp_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>quadratic_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mask_linp_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname> | |
gp_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>linear_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.int_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>In this setting, the choice of underlying hash-table affects | |
performance most, then the range-hashing scheme and, only finally, | |
other policies.</para> | |
<para>When comparing probing and chaining containers, it is | |
apparent that the probing containers are less efficient than the | |
collision-chaining containers ( | |
<classname>std::tr1::unordered_map</classname> uses | |
collision-chaining) in this case.</para> | |
<para>Hash-Based Integer Subscript Insert Timing Test shows | |
a different case, where the situation is reversed; | |
</para> | |
<para>Within each type of hash-table, the range-hashing scheme | |
affects performance more than other policies; Hash-Based Text | |
<function>find</function> Find Timing Test also shows this. In the | |
above graphics should be noted that | |
<classname>std::tr1::unordered_map</classname> are hard-wired | |
currently to mod-based schemes. | |
</para> | |
</section> | |
</section> | |
<!-- 03 <a href="hash_int_subscript_find_test"> --> | |
<section xml:id="performance.hash.int_subscript_find"> | |
<info><title> | |
Integer Subscript <function>find</function> | |
</title></info> | |
<para></para> | |
<section xml:id="hash.int_subscript_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with uniform | |
integer keys into a container, then performs a series of finds | |
using <function>operator[]</function>. It measures the average time | |
for <function>operator[]</function> as a function of the number of | |
values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/random_int_subscript_find_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different underlying | |
hash-tables, range-hashing functions, and trigger policies.</para> | |
</section> | |
<section xml:id="hash.int_subscript_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para> | |
There are two sets of results for this type, one for | |
collision-chaining hashes, and one for general-probe hashes. | |
</para> | |
<para>The first graphic below shows the results for the native | |
and collision-chaining hash types, using as the function | |
applied an integer subscript timing test with | |
<function>find</function>. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_cc_hash_int_subscript_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_cc_hash_int_subscript_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 04 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
<para> | |
</para> | |
<para> | |
</para> | |
<para>And the second graphic shows the results for the native and | |
general-probe hash types. The function applied being a random | |
integer timing test using <function>find</function>. | |
</para> | |
<!-- results graphic 02 --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_gp_hash_int_subscript_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_gp_hash_int_subscript_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mod_quadp_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname>gp_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>quadratic_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mask_linp_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname> | |
gp_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>linear_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.int_subscript_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>This test shows similar results to Hash-Based | |
Integer <classname>find</classname> Find Timing test.</para> | |
</section> | |
</section> | |
<!-- 04 <a href="hash_random_int_subscript_insert_timing_test"> --> | |
<section xml:id="performance.hash.int_subscript_insert"> | |
<info><title> | |
Integer Subscript <function>insert</function> | |
</title></info> | |
<para></para> | |
<section xml:id="hash.int_subscript_insert.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with uniform i.i.d. | |
integer keys into a container, using | |
<function>operator[]</function>. It measures the average time for | |
<function>operator[]</function> as a function of the number of | |
values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/random_int_subscript_insert_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different underlying | |
hash-tables.</para> | |
</section> | |
<section xml:id="hash.int_subscript_insert.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para> | |
There are two sets of results for this type, one for | |
collision-chaining hashes, and one for general-probe hashes. | |
</para> | |
<para>The first graphic below shows the results for the native | |
and collision-chaining hash types, using as the function | |
applied an integer subscript timing test with | |
<function>insert</function>. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_cc_hash_int_subscript_insert.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_cc_hash_int_subscript_insert.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 04 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
<para> | |
</para> | |
<para> | |
</para> | |
<para>And the second graphic shows the results for the native and | |
general-probe hash types. The function applied being a random | |
integer timing test using <function>find</function>. | |
</para> | |
<!-- results graphic 02 --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_gp_hash_int_subscript_insert.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_gp_hash_int_subscript_insert.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mod_quadp_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname>gp_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>quadratic_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mask_linp_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname> | |
gp_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>linear_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.int_subscript_insert.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>In this setting, as in Hash-Based Text | |
<function>find</function> Find Timing test and Hash-Based | |
Integer <function>find</function> Find Timing test , the choice | |
of underlying hash-table underlying hash-table affects performance | |
most, then the range-hashing scheme, and | |
finally any other policies.</para> | |
<para>There are some differences, however:</para> | |
<orderedlist> | |
<listitem><para>In this setting, probing tables function sometimes more | |
efficiently than collision-chaining tables. | |
This is explained shortly.</para></listitem> | |
<listitem><para>The performance graphs have a "saw-tooth" shape. The | |
average insert time rises and falls. As values are inserted | |
into the container, the load factor grows larger. Eventually, | |
a resize occurs. The reallocations and rehashing are | |
relatively expensive. After this, the load factor is smaller | |
than before.</para></listitem> | |
</orderedlist> | |
<para>Collision-chaining containers use indirection for greater | |
flexibility; probing containers store values contiguously, in | |
an array (see Figure Motivation::Different | |
underlying data structures A and B, respectively). It | |
follows that for simple data types, probing containers access | |
their allocator less frequently than collision-chaining | |
containers, (although they still have less efficient probing | |
sequences). This explains why some probing containers fare | |
better than collision-chaining containers in this case.</para> | |
<para> | |
Within each type of hash-table, the range-hashing scheme affects | |
performance more than other policies. This is similar to the | |
situation in Hash-Based Text | |
<function>find</function> Find Timing Test and Hash-Based | |
Integer <function>find</function> Find Timing Test. | |
Unsurprisingly, however, containers with lower α<subscript>max</subscript> perform worse in this case, | |
since more re-hashes are performed.</para> | |
</section> | |
</section> | |
<!-- 05 <a href="hash_zlob_random_int_find_find_timing_test"> --> | |
<!-- 05 <a href="hash_zlob_random_int_find_find_timing_test"> --> | |
<section xml:id="performance.hash.zlob_int_find"> | |
<info><title> | |
Integer <function>find</function> with Skewed-Distribution | |
</title></info> | |
<para></para> | |
<section xml:id="hash.zlob_int_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with a markedly | |
non-uniform integer keys into a container, then performs | |
a series of finds using <function>find</function>. It measures the average | |
time for <function>find</function> as a function of the number of values in | |
the containers. The keys are generated as follows. First, a | |
uniform integer is created. Then it is then shifted left 8 bits.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/hash_zlob_random_int_find_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different range-hashing | |
functions and trigger policies.</para> | |
</section> | |
<section xml:id="hash.zlob_int_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic below show the results for the native, collision-chaining, and general-probing hash types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_hash_zlob_int_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_hash_zlob_int_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname> | |
cc_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mod_quadp_prime_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname>gp_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>quadratic_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.zlob_int_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>In this setting, the distribution of keys is so skewed that | |
the underlying hash-table type affects performance marginally. | |
(This is in contrast with Hash-Based Text | |
<function>find</function> Find Timing Test, Hash-Based | |
Integer <function>find</function> Find Timing Test, Hash-Based | |
Integer Subscript Find Timing Test and Hash-Based | |
Integer Subscript Insert Timing Test.)</para> | |
<para>The range-hashing scheme affects performance dramatically. A | |
mask-based range-hashing scheme effectively maps all values | |
into the same bucket. Access degenerates into a search within | |
an unordered linked-list. In the graphic above, it should be noted that | |
<classname>std::tr1::unordered_map</classname> is hard-wired currently to mod-based and mask-based schemes, | |
respectively.</para> | |
<para>When observing the settings of this test, it is apparent | |
that the keys' distribution is far from natural. One might ask | |
if the test is not contrived to show that, in some cases, | |
mod-based range hashing does better than mask-based range | |
hashing. This is, in fact just the case. A | |
more natural case in which mod-based range hashing is better was not encountered. | |
Thus the inescapable conclusion: real-life key distributions are handled better | |
with an appropriate hash function and a mask-based | |
range-hashing function. (<filename>pb_ds/example/hash_shift_mask.cc</filename> | |
shows an example of handling this a-priori known skewed | |
distribution with a mask-based range-hashing function). If hash | |
performance is bad, a χ<superscript>2</superscript> test can be used | |
to check how to transform it into a more uniform | |
distribution.</para> | |
<para>For this reason, this library's default range-hashing | |
function is mask-based.</para> | |
</section> | |
</section> | |
<!-- 06 <a href="hash_random_int_erase_mem_usage_test"> --> | |
<!-- 06 <a href="hash_random_int_erase_mem_usage_test"> --> | |
<section xml:id="performance.hash.erase_mem"> | |
<info><title> | |
Erase Memory Use | |
</title></info> | |
<para></para> | |
<section xml:id="hash.erase_mem.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of uniform integer keys | |
into a container, then erases all keys except one. It measures | |
the final size of the container.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/hash_random_int_erase_mem_usage.cc</filename> | |
</para> | |
<para>The test checks how containers adjust internally as their | |
logical size decreases.</para> | |
</section> | |
<section xml:id="hash.erase_mem.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic below show the results for the native, collision-chaining, and general-probing hash types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_hash_int_erase_mem.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_hash_int_erase_mem.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="5" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<colspec colname="c4"/> | |
<colspec colname="c5"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
n_hash_map_ncah | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::tr1::unordered_map</classname> | |
</entry> | |
<entry> | |
<classname>cache_hash_code</classname> | |
</entry> | |
<entry> | |
<constant>false</constant> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<!-- hash 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mod_prime_1div1_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname>cc_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mod_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_prime_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/1 | |
</entry> | |
</row> | |
<!-- hash 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
cc_hash_mask_exp_1div2_nsth_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="2" valign="top"> | |
<classname> | |
cc_hash_table | |
</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
<!-- hash 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c5"> | |
gp_hash_mask_linp_exp_1div2_nsth_set | |
</entry> | |
</row> | |
<row> | |
<entry morerows="3" valign="top"> | |
<classname>gp_hash_table</classname> | |
</entry> | |
<entry> | |
<classname>Comb_Hash_Fn</classname> | |
</entry> | |
<entry> | |
<classname>direct_mask_range_hashing</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Probe_Fn</classname> | |
</entry> | |
<entry> | |
<classname>linear_probe_fn</classname> | |
</entry> | |
<entry namest="c4" nameend="c5"></entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>Resize_Policy</classname> | |
</entry> | |
<entry morerows="1" valign="top"> | |
<classname>hash_standard_resize_policy</classname> | |
</entry> | |
<entry> | |
<classname>Size_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_exponential_size_policy</classname> | |
</entry> | |
</row> | |
<row> | |
<entry valign="top"> | |
<classname>Trigger_Policy</classname> | |
</entry> | |
<entry> | |
<classname>hash_load_check_resize_trigger</classname> with | |
α<subscript>min</subscript> = 1/8 and α<subscript>max</subscript> = 1/2 | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="hash.erase_mem.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>The standard's hash-based containers act very differently than trees in | |
this respect. When erasing numerous keys from an standard | |
associative-container, the resulting memory user varies greatly | |
depending on whether the container is tree-based or hash-based. | |
This is a fundamental consequence of the standard's interface for | |
associative containers, and it is not due to a specific | |
implementation.</para> | |
</section> | |
</section> | |
</section> | |
<section xml:id="performance.branch"> | |
<info><title>Branch-Based</title></info> | |
<para></para> | |
<!-- 01 <a href="tree_text_insert_timing_test"> --> | |
<section xml:id="performance.branch.text_insert"> | |
<info><title> | |
Text <function>insert</function> | |
</title></info> | |
<para></para> | |
<section xml:id="branch.text_insert.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with keys from an arbitrary | |
text ([wickland96thirty]) into a container | |
using <function>insert</function> . It measures the average time | |
for <function>insert</function> as a function of the number of | |
values inserted.</para> | |
<para>The test checks the effect of different underlying | |
data structures.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/tree_text_insert_timing.cc</filename> | |
</para> | |
</section> | |
<section xml:id="branch.text_insert.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The three graphics below show the results for the native | |
tree and this library's node-based trees, the native tree and | |
this library's vector-based trees, and the native tree | |
and this library's PATRICIA-trie, respectively. | |
</para> | |
<para>The graphic immediately below shows the results for the | |
native tree type and several node-based tree types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_text_insert_node.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_text_insert_node.png"/> | |
</imageobject> | |
</mediaobject> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
</informalfigure> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_map | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::map</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
splay_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>splay_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
rb_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>rb_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
<para>The graphic below shows the results for the | |
native tree type and a vector-based tree type. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_text_insert_vector.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_text_insert_vector.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_map | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::map</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
ov_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>ov_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
<para>The graphic below shows the results for the | |
native tree type and a PATRICIA trie type. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_text_insert_trie.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_text_insert_trie.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_map | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::map</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
pat_trie_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>pat_trie_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="branch.text_insert.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>Observing the first graphic implies that for this setting, a splay tree | |
(<classname>tree</classname> with <classname>Tag | |
</classname> = <classname>splay_tree_tag</classname>) does not do | |
well. See also the Branch-Based | |
Text <function>find</function> Find Timing Test. The two | |
red-black trees perform better.</para> | |
<para>Observing the second graphic, an ordered-vector tree | |
(<classname>tree</classname> with <classname>Tag | |
</classname> = <classname>ov_tree_tag</classname>) performs | |
abysmally. Inserting into this type of tree has linear complexity | |
[ austern00noset].</para> | |
<para>Observing the third and last graphic, A PATRICIA trie | |
(<classname>trie</classname> with <classname>Tag | |
</classname> = <classname>pat_trie_tag</classname>) has abysmal | |
performance, as well. This is not that surprising, since a | |
large-fan-out PATRICIA trie works like a hash table with | |
collisions resolved by a sub-trie. Each time a collision is | |
encountered, a new "hash-table" is built A large fan-out PATRICIA | |
trie, however, doe does well in look-ups (see Branch-Based | |
Text <function>find</function> Find Timing Test). It may be | |
beneficial in semi-static settings.</para> | |
</section> | |
</section> | |
<!-- 02 <a href="tree_text_find_find_timing_test"> --> | |
<section xml:id="performance.branch.text_find"> | |
<info><title> | |
Text <function>find</function> | |
</title></info> | |
<para></para> | |
<section xml:id="branch.text_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with keys from an | |
arbitrary text ([wickland96thirty]) into | |
a container, then performs a series of finds using | |
<function>find</function>. It measures the average time | |
for <function>find</function> as a function of the number of | |
values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/text_find_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different underlying | |
data structures.</para> | |
</section> | |
<section xml:id="branch.text_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic immediately below shows the results for the | |
native tree type and several other tree types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_text_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_text_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_map | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::map</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
splay_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>splay_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
rb_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>rb_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
ov_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>ov_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 05 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
pat_trie_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>pat_trie_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="branch.text_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>For this setting, a splay tree (<classname>tree</classname> | |
with <classname>Tag | |
</classname> = <classname>splay_tree_tag</classname>) does not do | |
well. This is possibly due to two reasons:</para> | |
<orderedlist> | |
<listitem><para>A splay tree is not guaranteed to be balanced [motwani95random]. If a | |
splay tree contains n nodes, its average root-leaf | |
path can be m >> log(n).</para></listitem> | |
<listitem><para>Assume a specific root-leaf search path has length | |
m, and the search-target node has distance m' | |
from the root. A red-black tree will require m + 1 | |
comparisons to find the required node; a splay tree will | |
require 2 m' comparisons. A splay tree, consequently, | |
can perform many more comparisons than a red-black tree.</para></listitem> | |
</orderedlist> | |
<para>An ordered-vector tree (<classname>tree</classname> | |
with <classname>Tag</classname> = <classname>ov_tree_tag</classname>), a red-black | |
tree (<classname>tree</classname> | |
with <classname>Tag</classname> = <classname>rb_tree_tag</classname>), and the | |
native red-black tree all share approximately the same | |
performance.</para> | |
<para>An ordered-vector tree is slightly slower than red-black | |
trees, since it requires, in order to find a key, more math | |
operations than they do. Conversely, an ordered-vector tree | |
requires far lower space than the others. ([austern00noset], however, | |
seems to have an implementation that is also faster than a | |
red-black tree).</para> | |
<para>A PATRICIA trie (<classname>trie</classname> | |
with <classname>Tag</classname> = <classname>pat_trie_tag</classname>) has good | |
look-up performance, due to its large fan-out in this case. In | |
this setting, a PATRICIA trie has look-up performance comparable | |
to a hash table (see Hash-Based Text | |
<classname>find</classname> Timing Test), but it is order | |
preserving. This is not that surprising, since a large-fan-out | |
PATRICIA trie works like a hash table with collisions resolved | |
by a sub-trie. A large-fan-out PATRICIA trie does not do well on | |
modifications (see Tree-Based and Trie-Based | |
Text Insert Timing Test). Therefore, it is possibly beneficial in | |
semi-static settings.</para> | |
</section> | |
</section> | |
<!-- 03 <a href="tree_text_lor_find_find_timing_test"> --> | |
<section xml:id="performance.branch.text_lor_find"> | |
<info><title> | |
Text <function>find</function> with Locality-of-Reference | |
</title></info> | |
<para></para> | |
<section xml:id="branch.text_lor_find.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test inserts a number of values with keys from an | |
arbitrary text ([wickland96thirty]) into | |
a container, then performs a series of finds using | |
<function>find</function>. It is different than Tree-Based and | |
Trie-Based Text <function>find</function> Find Timing Test in the | |
sequence of finds it performs: this test performs multiple | |
<function>find</function>s on the same key before moving on to the next | |
key. It measures the average time for <function>find</function> as a | |
function of the number of values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/tree_text_lor_find_timing.cc</filename> | |
</para> | |
<para>The test checks the effect of different underlying | |
data structures in a locality-of-reference setting.</para> | |
</section> | |
<section xml:id="branch.text_lor_find.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic immediately below shows the results for the | |
native tree type and several other tree types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_text_lor_find.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_text_lor_find.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_map | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::map</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
splay_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>splay_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 02 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
rb_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>rb_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 03 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
ov_tree_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>ov_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
<!-- branch 05 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
pat_trie_map | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>pat_trie_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |
<classname>null_node_update</classname> | |
</entry> | |
</row> | |
</tbody> | |
</tgroup> | |
</informaltable> | |
</section> | |
<section xml:id="branch.text_lor_find.observations"> | |
<info><title> | |
Observations | |
</title></info> | |
<para>For this setting, an ordered-vector tree | |
(<classname>tree</classname> with <classname>Tag</classname> | |
= <classname>ov_tree_tag</classname>), a red-black tree | |
(<classname>tree</classname> with <classname>Tag</classname> | |
= <classname>rb_tree_tag</classname>), and the native red-black | |
tree all share approximately the same performance.</para> | |
<para>A splay tree (<classname>tree</classname> | |
with <classname>Tag</classname> = <classname>splay_tree_tag</classname>) does | |
much better, since each (successful) find "bubbles" the | |
corresponding node to the root of the tree.</para> | |
</section> | |
</section> | |
<!-- 04 <a href="tree_split_join_timing_test"> --> | |
<section xml:id="performance.branch.split_join"> | |
<info><title> | |
<function>split</function> and <function>join</function> | |
</title></info> | |
<para></para> | |
<section xml:id="branch.split_join.info"> | |
<info><title> | |
Description | |
</title></info> | |
<para>This test a container, inserts into a number of values, splits | |
the container at the median, and joins the two containers. (If the | |
containers are one of this library's trees, | |
it splits and joins with the <function>split</function> and | |
<function>join</function> method; otherwise, it uses the <function>erase</function> and | |
<function>insert</function> methods.) It measures the time for splitting | |
and joining the containers as a function of the number of | |
values inserted.</para> | |
<para> | |
It uses the test file: | |
<filename>performance/ext/pb_ds/tree_split_join_timing.cc</filename> | |
</para> | |
<para>The test checks the performance difference of <function>join</function> | |
as opposed to a sequence of <function>insert</function> operations; by | |
implication, this test checks the most efficient way to erase a | |
sub-sequence from a tree-like-based container, since this can | |
always be performed by a small sequence of splits and joins. | |
</para> | |
</section> | |
<section xml:id="branch.split_join.results"> | |
<info><title> | |
Results | |
</title></info> | |
<para>The graphic immediately below shows the results for the | |
native tree type and several other tree types. | |
</para> | |
<!-- results graphic --> | |
<informalfigure> | |
<mediaobject> | |
<imageobject> | |
<imagedata align="center" format="PDF" scale="75" | |
fileref="../images/pbds_tree_split_join.pdf"/> | |
</imageobject> | |
<imageobject> | |
<imagedata align="center" format="PNG" scale="100" | |
fileref="../images/pbds_tree_split_join.png"/> | |
</imageobject> | |
</mediaobject> | |
</informalfigure> | |
<para> | |
The abbreviated names in the legend of the graphic above are | |
instantiated with the types in the following table. | |
</para> | |
<informaltable frame="all"> | |
<tgroup cols="3" align="left" colsep="1" rowsep="1"> | |
<colspec colname="c1"/> | |
<colspec colname="c2"/> | |
<colspec colname="c3"/> | |
<thead> | |
<row> | |
<entry><emphasis>Name/Instantiating Type</emphasis></entry> | |
<entry><emphasis>Parameter</emphasis></entry> | |
<entry><emphasis>Details</emphasis></entry> | |
</row> | |
</thead> | |
<tbody> | |
<!-- native --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
n_set | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>std::set</classname> | |
</entry> | |
<entry namest="c2" nameend="c3"></entry> | |
</row> | |
<!-- branch 01 --> | |
<row> | |
<?dbhtml bgcolor="#B0B0B0" ?> | |
<entry namest="c1" nameend="c3"> | |
splay_tree_set | |
</entry> | |
</row> | |
<row> | |
<entry morerows="1" valign="top"> | |
<classname>tree</classname> | |
</entry> | |
<entry> | |
<classname>Tag</classname> | |
</entry> | |
<entry> | |
<classname>splay_tree_tag</classname> | |
</entry> | |
</row> | |
<row> | |
<entry> | |
<classname>Node_Update</classname> | |
</entry> | |
<entry> | |