blob: cb5b016569ac145f118821d5ccc7248ef62a0221 [file] [log] [blame]
<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 &gt;&gt; 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>