mirror of
https://github.com/autc04/Retro68.git
synced 2024-07-28 21:29:18 +00:00
9774 lines
245 KiB
XML
9774 lines
245 KiB
XML
<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>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 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>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- branch 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rb_tree_set
|
||
</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_set
|
||
</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.split_join.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>In this test, the native red-black trees must be split and
|
||
joined externally, through a sequence of <function>erase</function> and
|
||
<function>insert</function> operations. This is clearly
|
||
super-linear, and it is not that surprising that the cost is
|
||
high.</para>
|
||
<para>This library's tree-based containers use in this test the
|
||
<function>split</function> and <function>join</function> methods,
|
||
which have lower complexity: the <function>join</function> method
|
||
of a splay tree (<classname>tree</classname>
|
||
with <classname>Tag </classname>
|
||
= <classname>splay_tree_tag</classname>) is quadratic in the
|
||
length of the longest root-leaf path, and linear in the total
|
||
number of elements; the <function>join</function> method of a
|
||
red-black tree (<classname>tree</classname>
|
||
with <classname>Tag </classname>
|
||
= <classname>rb_tree_tag</classname>) or an ordered-vector tree
|
||
(<classname>tree</classname> with <classname>Tag </classname>
|
||
= <classname>ov_tree_tag</classname>) is linear in the number of
|
||
elements.</para>
|
||
|
||
<para>Asides from orders of growth, this library's trees access their
|
||
allocator very little in these operations, and some of them do not
|
||
access it at all. This leads to lower constants in their
|
||
complexity, and, for some containers, to exception-free splits and
|
||
joins (which can be determined
|
||
via <classname>container_traits</classname>).</para>
|
||
|
||
<para>It is important to note that <function>split</function> and
|
||
<function>join</function> are not esoteric methods - they are the most
|
||
efficient means of erasing a contiguous range of values from a
|
||
tree based container.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<!-- 05 <a href="tree_order_statistics_timing_test"> -->
|
||
<section xml:id="performance.branch.order_statistics">
|
||
|
||
<info><title>
|
||
Order-Statistics
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="branch.order_statistics.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test creates a container, inserts random integers into the
|
||
the container, and then checks the order-statistics of the
|
||
container's values. (If the container is one of this
|
||
library's trees, it does this with
|
||
the <function>order_of_key</function> method of
|
||
<classname>tree_order_statistics_node_update</classname>
|
||
; otherwise, it uses the <function>find</function> method and
|
||
<function>std::distance</function>.) It measures the average
|
||
time for such queries as a function of the number of values
|
||
inserted.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/tree_order_statistics_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the performance difference of policies based
|
||
on node-invariant as opposed to a external functions.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="branch.order_statistics.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_order_statistics.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_tree_order_statistics.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_ost_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>
|
||
<classname>tree_order_statistics_node_update</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- branch 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rb_tree_ost_set
|
||
</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>tree_order_statistics_node_update</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
</section>
|
||
|
||
<section xml:id="branch.order_statistics.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
<para>In this test, the native red-black tree can support
|
||
order-statistics queries only externally, by performing a
|
||
<classname>find</classname> (alternatively, <classname>lower_bound</classname> or
|
||
<classname>upper_bound</classname> ) and then using <classname>std::distance</classname> .
|
||
This is clearly linear, and it is not that surprising that the
|
||
cost is high.</para>
|
||
<para>This library's tree-based containers use in this test the
|
||
<classname>order_of_key</classname> method of <classname>tree_order_statistics_node_update</classname>.
|
||
This method has only linear complexity in the length of the
|
||
root-node path. Unfortunately, the average path of a splay tree
|
||
(<classname>tree</classname>
|
||
with <classname>Tag =</classname> <classname>splay_tree_tag</classname> ) can
|
||
be higher than logarithmic; the longest path of a red-black
|
||
tree (<classname>tree</classname>
|
||
with <classname>Tag =</classname> <classname>rb_tree_tag</classname> ) is
|
||
logarithmic in the number of elements. Consequently, the splay
|
||
tree has worse performance than the red-black tree.</para>
|
||
</section>
|
||
</section>
|
||
|
||
</section> <!-- branch -->
|
||
|
||
<section xml:id="performance.multimap">
|
||
<info><title>Multimap</title></info>
|
||
<para></para>
|
||
|
||
|
||
<!-- 01 <a href="multimap_text_find_timing_test_small"> -->
|
||
<section xml:id="performance.multimap.text_find_small">
|
||
<info><title>
|
||
Text <function>find</function> with Small Secondary-to-Primary Key Ratios
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_find_small.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform i.i.d.integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key (see Motivation::Associative
|
||
Containers::Alternative to Multiple Equivalent Keys). There
|
||
are 400 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges from 1 to 5.</para>
|
||
<para>The test measures the average find-time as a function of the
|
||
number of values inserted. For this library's containers, it
|
||
finds the secondary key from a container obtained from finding
|
||
a primary key. For the native multimaps, it searches a range
|
||
obtained using <classname>std::equal_range</classname> on a primary key.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_find_timing_small.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the find-time scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_find_small.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_find_small.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
<!-- 02 <a href="multimap_text_find_timing_test_large"> -->
|
||
<section xml:id="performance.multimap.text_find_large">
|
||
<info><title>
|
||
Text <function>find</function> with Large Secondary-to-Primary Key Ratios
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_find_large.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key. There
|
||
are 400 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges from 1 to 5.</para>
|
||
<para>The test measures the average find-time as a function of the
|
||
number of values inserted. For this library's containers, it
|
||
finds the secondary key from a container obtained from finding
|
||
a primary key. For the native multimaps, it searches a range
|
||
obtained using <classname>std::equal_range</classname> on a primary key.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_find_timing_large.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the find-time scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_find_large.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_find_large.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<!-- 03 <a href="multimap_text_insert_timing_test_small"> -->
|
||
<section xml:id="performance.multimap.text_insert_small">
|
||
<info><title>
|
||
Text <function>insert</function> with Small
|
||
Secondary-to-Primary Key Ratios
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_insert_small.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key. There
|
||
are 400 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges from 1 to 5.</para>
|
||
<para>The test measures the average insert-time as a function of
|
||
the number of values inserted. For this library's containers,
|
||
it inserts a primary key into the primary associative
|
||
container, then a secondary key into the secondary associative
|
||
container. For the native multimaps, it obtains a range using
|
||
<classname>std::equal_range</classname>, and inserts a value only if it was
|
||
not contained already.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_insert_timing_small.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the insert-time scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_insert_small.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_insert_small_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_insert_small_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_small_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_insert_small.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<!-- 04 <a href="multimap_text_insert_timing_test_large"> -->
|
||
<section xml:id="performance.multimap.text_insert_large">
|
||
<info><title>
|
||
Text <function>insert</function> with Small
|
||
Secondary-to-Primary Key Ratios
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_insert_large.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key. There
|
||
are 400 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges from 1 to 5.</para>
|
||
<para>The test measures the average insert-time as a function of
|
||
the number of values inserted. For this library's containers,
|
||
it inserts a primary key into the primary associative
|
||
container, then a secondary key into the secondary associative
|
||
container. For the native multimaps, it obtains a range using
|
||
<classname>std::equal_range</classname>, and inserts a value only if it was
|
||
not contained already.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_insert_timing_large.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the insert-time scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_insert_large.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_insert_large_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_insert_large_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_insert_large.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<!-- 05 <a href="multimap_text_insert_mem_usage_test_small"> -->
|
||
<section xml:id="performance.multimap.text_insert_mem_small">
|
||
<info><title>
|
||
Text <function>insert</function> with Small
|
||
Secondary-to-Primary Key Ratios Memory Use
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_insert_mem_small.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key. There
|
||
are 100 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges to about 20.</para>
|
||
<para>The test measures the memory use as a function of the number
|
||
of values inserted.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_insert_mem_usage_small.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the memory scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_insert_mem_small.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_insert_mem_small_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_insert_mem_small_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_insert_mem_small.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
<!-- 06 <a href="multimap_text_insert_mem_usage_test_large"> -->
|
||
<section xml:id="performance.multimap.text_insert_mem_large">
|
||
<info><title>
|
||
Text <function>insert</function> with Small
|
||
Secondary-to-Primary Key Ratios Memory Use
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="multimap.text_insert_mem_large.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
<para>This test inserts a number of pairs into a container. The
|
||
first item of each pair is a string from an arbitrary text
|
||
[wickland96thirty], and
|
||
the second is a uniform integer. The container is a
|
||
"multimap" - it considers the first member of each pair as a
|
||
primary key, and the second member of each pair as a secondary
|
||
key. There
|
||
are 100 distinct primary keys, and the ratio of secondary keys
|
||
to primary keys ranges to about 20.</para>
|
||
<para>The test measures the memory use as a function of the number
|
||
of values inserted.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/multimap_text_insert_mem_usage_large.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the memory scalability of different
|
||
"multimap" designs.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="multimap.text_insert_mem_large.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic below show the results for "multimaps" which
|
||
use a tree-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_insert_mem_large_s2p_tree.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_insert_mem_large_s2p_tree.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="4" valign="top">
|
||
<classname>tree</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rb_tree_tag</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Node_Update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>null_node_update</classname>
|
||
</entry>
|
||
<entry namest="c4" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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>The graphic below show the results for "multimaps" which
|
||
use a hash-based container for primary keys.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.png"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="33"
|
||
fileref="../images/pbds_multimap_text_find_large_s2p_hash.pdf"/>
|
||
</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="7" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<colspec colname="c7"/>
|
||
<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>
|
||
<entry><emphasis>Parameter</emphasis></entry>
|
||
<entry><emphasis>Details</emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<!-- native -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
n_hash_mmap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::tr1::unordered_multimap</classname>
|
||
</entry>
|
||
<entry namest="c2" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_lu_mtf_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="3" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>list_update</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Update_Policy</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>lu_move_to_front_policy</classname>
|
||
</entry>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<!-- multimap 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c7">
|
||
rb_tree_mmap_cc_hash_mask_exp_1div2_nsth_set
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="5" 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="c7"></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>
|
||
<entry namest="c6" nameend="c7"></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>
|
||
<entry namest="c6" nameend="c7"></entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry morerows="2" valign="top">
|
||
<classname>Mapped</classname>
|
||
</entry>
|
||
<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="c6" nameend="c7"></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="multimap.text_insert_mem_large.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>See Observations::Mapping-Semantics
|
||
Considerations.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
</section> <!-- multimap -->
|
||
|
||
<section xml:id="performance.priority_queue">
|
||
<info><title>Priority Queue</title></info>
|
||
|
||
<!-- 01 <a href="priority_queue_text_push_timing_test"> -->
|
||
<section xml:id="performance.priority_queue.text_push">
|
||
<info><title>
|
||
Text <function>push</function>
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_push.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>push</function>. It measures the average time
|
||
for <function>push</function> as a function of the number of values
|
||
pushed.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_push_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_push.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The two graphics below show the results for the native
|
||
priority_queues and this library's priority_queues.
|
||
</para>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_push.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_push.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
<para>The graphic below shows the results for the binary-heap
|
||
based native priority queues and this library's pairing-heap
|
||
priority_queue data structures.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_pairing_priority_queue_text_push.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_pairing_priority_queue_text_push.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_push.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>Pairing heaps (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>pairing_heap_tag</classname>)
|
||
are the most suited for sequences of <function>push</function> and
|
||
<function>pop</function> operations of non-primitive types (e.g.
|
||
<classname>std::string</classname>s). (See Priority Queue
|
||
Text <function>push</function> and <function>pop</function> Timing Test.) They are
|
||
less constrained than binomial heaps, e.g., and since
|
||
they are node-based, they outperform binary heaps. (See
|
||
Priority
|
||
Queue Random Integer <function>push</function> Timing Test for the case
|
||
of primitive types.)</para>
|
||
|
||
<para>The standard's priority queues do not seem to perform well in
|
||
this case: the <classname>std::vector</classname> implementation needs to
|
||
perform a logarithmic sequence of string operations for each
|
||
operation, and the deque implementation is possibly hampered by
|
||
its need to manipulate a relatively-complex type (deques
|
||
support a O(1) <function>push_front</function>, even though it is
|
||
not used by <classname>std::priority_queue</classname>.)</para>
|
||
|
||
</section>
|
||
</section>
|
||
|
||
<!-- 02 <a href="priority_queue_text_push_pop_timing_test"> -->
|
||
<section xml:id="performance.priority_queue.text_push_pop">
|
||
<info><title>
|
||
Text <function>push</function> and <function>pop</function>
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_push_pop.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 <classname>push</classname> , then removes them using
|
||
<classname>pop</classname> . It measures the average time for <classname>push</classname>
|
||
as a function of the number of values.</para>
|
||
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_push_pop_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_push_pop.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The two graphics below show the results for the native
|
||
priority_queues and this library's priority_queues.
|
||
</para>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_push_pop.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_push_pop.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
<para>The graphic below shows the results for the native priority
|
||
queues and this library's pairing-heap priority_queue data
|
||
structures.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_pairing_priority_queue_text_push_pop.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_pairing_priority_queue_text_push_pop.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname> adapting <classname>std::vector</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_push_pop.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>These results are very similar to Priority Queue Text
|
||
<function>push</function> Timing Test. As stated there, pairing heaps
|
||
(<classname>priority_queue</classname> with
|
||
<classname>Tag</classname>
|
||
= <classname>pairing_heap_tag</classname>) are most suited
|
||
for <function>push</function> and <function>pop</function>
|
||
sequences of non-primitive types such as strings. Observing these
|
||
two tests, one can note that a pairing heap outperforms the others
|
||
in terms of <function>push</function> operations, but equals
|
||
binary heaps (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname>
|
||
= <classname>binary_heap_tag</classname>) if the number
|
||
of <function>push</function> and <function>pop</function>
|
||
operations is equal. As the number of <function>pop</function>
|
||
operations is at most equal to the number
|
||
of <function>push</function> operations, pairing heaps are better
|
||
in this case. See Priority Queue Random
|
||
Integer <function>push</function> and <function>pop</function>
|
||
Timing Test for a case which is different.</para>
|
||
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<!-- 03 <a href="priority_queue_random_int_push_timing_test"> -->
|
||
<section xml:id="performance.priority_queue.int_push">
|
||
<info><title>
|
||
Integer <function>push</function>
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.int_push.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of values with integer keys
|
||
into a container using <function>push</function>. It
|
||
measures the average time for <function>push</function> as a
|
||
function of the number of values.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_random_int_push_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.int_push.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The two graphics below show the results for the native
|
||
priority_queues and this library's priority_queues.
|
||
</para>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_int_push.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_int_push.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
<para>The graphic below shows the results for the binary-heap
|
||
based native priority queues and this library's
|
||
priority_queue data structures.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_binary_priority_queue_int_push.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_binary_priority_queue_int_push.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname> adapting <classname>std::vector</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.int_push.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
|
||
<para>Binary heaps are the most suited for sequences of
|
||
<function>push</function> and <function>pop</function> operations of primitive types
|
||
(e.g. <type>int</type>s). They are less constrained
|
||
than any other type, and since it is very efficient to store
|
||
such types in arrays, they outperform even pairing heaps. (See
|
||
Priority
|
||
Queue Text <function>push</function> Timing Test for the case of
|
||
non-primitive types.)</para>
|
||
</section>
|
||
</section>
|
||
|
||
<!-- 04 "priority_queue_random_int_push_pop_timing_test" -->
|
||
<section xml:id="performance.priority_queue.int_push_pop">
|
||
<info><title>
|
||
Integer <function>push</function>
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.int_push_pop.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of values with integer keys
|
||
into a container using <function>push</function> , then removes them
|
||
using <function>pop</function> . It measures the average time for
|
||
<function>push</function> and <function>pop</function> as a function
|
||
of the number of values.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_random_int_push_pop_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.int_push_pop.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_int_push_pop.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_int_push_pop.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.int_push_pop.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>Binary heaps are the most suited for sequences of
|
||
<function>push</function> and <function>pop</function> operations of primitive types
|
||
(e.g. <type>int</type>s). This is explained in
|
||
Priority
|
||
Queue Random Int <function>push</function> Timing Test. (See Priority Queue
|
||
Text <function>push</function> Timing Test for the case of primitive
|
||
types.)</para>
|
||
|
||
<para>At first glance it seems that the standard's vector-based
|
||
priority queue is approximately on par with this
|
||
library's corresponding priority queue. There are two
|
||
differences however:</para>
|
||
<orderedlist>
|
||
<listitem><para>The standard's priority queue does not downsize the underlying
|
||
vector (or deque) as the priority queue becomes smaller
|
||
(see Priority Queue
|
||
Text <function>pop</function> Memory Use Test). It is therefore
|
||
gaining some speed at the expense of space.</para></listitem>
|
||
<listitem><para>From Priority Queue Random
|
||
Integer <function>push</function> and <function>pop</function>
|
||
Timing Test, it seems that the standard's priority queue is
|
||
slower in terms of <function>push</function> operations. Since
|
||
the number of
|
||
<function>pop</function> operations is at most that of <function>push</function>
|
||
operations, the test here is the "best" for the standard's
|
||
priority queue.</para></listitem>
|
||
</orderedlist>
|
||
|
||
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<!-- 05 <a href="priority_queue_text_pop_mem_usage_test"> -->
|
||
<section xml:id="performance.priority_queue.text_pop">
|
||
<info><title>
|
||
Text <function>pop</function> Memory Use
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_pop.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 pops them until only one is left in the
|
||
container. It measures the memory use as a function of the
|
||
number of values pushed to the container.</para>
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_pop_mem_usage.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_pop.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_pop_mem.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_pop_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="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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_pop.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
|
||
<para>The priority queue implementations (excluding the standard's) use
|
||
memory proportionally to the number of values they hold:
|
||
node-based implementations (e.g., a pairing heap) do so
|
||
naturally; this library's binary heap de-allocates memory when
|
||
a certain lower threshold is exceeded.</para>
|
||
|
||
<para>Note from Priority Queue Text <function>push</function>
|
||
and <function>pop</function> Timing Test and Priority Queue
|
||
Random Integer <function>push</function>
|
||
and <function>pop</function> Timing Test that this does not
|
||
impede performance compared to the standard's priority
|
||
queues.</para>
|
||
<para>See Hash-Based Erase
|
||
Memory Use Test for a similar phenomenon regarding priority
|
||
queues.</para>
|
||
</section>
|
||
</section>
|
||
|
||
<!-- 06 <a href="priority_queue_text_join_timing_test"> -->
|
||
<section xml:id="performance.priority_queue.text_join">
|
||
<info><title>
|
||
Text <function>join</function>
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_join.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of values with keys from an
|
||
arbitrary text ([ wickland96thirty ]) into
|
||
two containers, then merges the containers. It uses
|
||
<function>join</function> for this library's priority queues; for
|
||
the standard's priority queues, it successively pops values from
|
||
one container and pushes them into the other. The test measures
|
||
the average time as a function of the number of values.</para>
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_join_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures.
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_join.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_join.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_join.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>In this test the node-based heaps perform <function>join</function> in
|
||
either logarithmic or constant time. The binary heap requires
|
||
linear time, since the well-known heapify algorithm [clrs2001] is linear.</para>
|
||
<para>It would be possible to apply the heapify algorithm to the
|
||
standard containers, if they would support iteration (which they
|
||
don't). Barring iterators, it is still somehow possible to perform
|
||
linear-time merge on a <classname>std::vector</classname>-based
|
||
standard priority queue, using <function>top()</function>
|
||
and <function>size()</function> (since they are enough to expose
|
||
the underlying array), but this is impossible for
|
||
a <classname>std::deque</classname>-based standard priority queue.
|
||
Without heapify, the cost is super-linear.</para>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<!-- 07 <a href="priority_queue_text_push_timing_test"> -->
|
||
<section xml:id="performance.priority_queue.text_modify_up">
|
||
<info><title>
|
||
Text <function>modify</function> Up
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_modify_up.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of values with keys from an
|
||
arbitrary text ([ wickland96thirty ]) into
|
||
into a container then modifies each one "up" (i.e., it
|
||
makes it larger). It uses <function>modify</function> for this library's
|
||
priority queues; for the standard's priority queues, it pops values
|
||
from a container until it reaches the value that should be
|
||
modified, then pushes values back in. It measures the average
|
||
time for <function>modify</function> as a function of the number of
|
||
values.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_modify_up_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The test checks the effect of different underlying data
|
||
structures for graph algorithms settings. Note that making an
|
||
arbitrary value larger (in the sense of the priority queue's
|
||
comparison functor) corresponds to decrease-key in standard graph
|
||
algorithms [clrs2001].
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_modify_up.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The two graphics below show the results for the native
|
||
priority_queues and this library's priority_queues.
|
||
</para>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_modify_up.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_modify_up.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
<para>The graphic below shows the results for the
|
||
native priority queues and this library's pairing and thin heap
|
||
priority_queue data structures.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_pairing_priority_queue_text_modify_up_thin.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_pairing_priority_queue_text_modify_up_thin.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>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_modify_up.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>As noted above, increasing an arbitrary value (in the sense of
|
||
the priority queue's comparison functor) is very common in
|
||
graph-related algorithms. In this case, a thin heap
|
||
(<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>thin_heap_tag</classname>)
|
||
outperforms a pairing heap (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>pairing_heap_tag</classname>).
|
||
Conversely, Priority Queue Text
|
||
<function>push</function> Timing Test, Priority Queue
|
||
Text <function>push</function> and <function>pop</function> Timing Test, Priority
|
||
Queue Random Integer <function>push</function> Timing Test, and
|
||
Priority
|
||
Queue Random Integer <function>push</function> and <function>pop</function> Timing
|
||
Test show that the situation is reversed for other
|
||
operations. It is not clear when to prefer one of these two
|
||
different types.</para>
|
||
|
||
<para>In this test this library's binary heaps
|
||
effectively perform modify in linear time. As explained in
|
||
Priority Queue Design::Traits, given a valid point-type iterator,
|
||
a binary heap can perform
|
||
<function>modify</function> logarithmically. The problem is that binary
|
||
heaps invalidate their find iterators with each modifying
|
||
operation, and so the only way to obtain a valid point-type
|
||
iterator is to iterate using a range-type iterator until
|
||
finding the appropriate value, then use the range-type iterator
|
||
for the <function>modify</function> operation.</para>
|
||
<para>The explanation for the standard's priority queues' performance
|
||
is similar to that in Priority Queue Text
|
||
<function>join</function> Timing Test.</para>
|
||
|
||
|
||
</section>
|
||
</section>
|
||
|
||
<!-- 08 <a href="priority_queue_text_modify_down_timing_test"> -->
|
||
|
||
<section xml:id="performance.priority_queue.text_modify_down">
|
||
<info><title>
|
||
Text <function>modify</function> Down
|
||
</title></info>
|
||
<para></para>
|
||
|
||
<section xml:id="priority_queue.text_modify_down.info">
|
||
<info><title>
|
||
Description
|
||
</title></info>
|
||
|
||
<para>This test inserts a number of values with keys from an
|
||
arbitrary text ([ wickland96thirty ]) into
|
||
into a container then modifies each one "down" (i.e., it
|
||
makes it smaller). It uses <function>modify</function> for this library's
|
||
priority queues; for the standard's priority queues, it pops values
|
||
from a container until it reaches the value that should be
|
||
modified, then pushes values back in. It measures the average
|
||
time for <function>modify</function> as a function of the number of
|
||
values.</para>
|
||
|
||
<para>
|
||
It uses the test file:
|
||
<filename>
|
||
performance/ext/pb_ds/priority_queue_text_modify_down_timing.cc
|
||
</filename>
|
||
</para>
|
||
|
||
<para>The main purpose of this test is to contrast Priority Queue
|
||
Text <classname>modify</classname> Up Timing Test.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_modify_down.results">
|
||
<info><title>
|
||
Results
|
||
</title></info>
|
||
|
||
<para>The two graphics below show the results for the native
|
||
priority_queues and this library's priority_queues.
|
||
</para>
|
||
|
||
<para>The graphic immediately below shows the results for the
|
||
native priority_queue type instantiated with different underlying
|
||
container types versus several different versions of library's
|
||
priority_queues.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_priority_queue_text_modify_down.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_priority_queue_text_modify_down.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 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_vector
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::vector</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- native 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
n_pq_deque
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Sequence</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>std::deque</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binary_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binary_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 03 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
rc_binomial_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>rc_binomial_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
<!-- priority_queue 04 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 05 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
|
||
<para>The graphic below shows the results for the
|
||
native priority queues and this library's pairing and thin heap
|
||
priority_queue data structures.
|
||
</para>
|
||
|
||
<!-- results graphic -->
|
||
<informalfigure>
|
||
<mediaobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PDF" scale="75"
|
||
fileref="../images/pbds_pairing_priority_queue_text_modify_down_thin.pdf"/>
|
||
</imageobject>
|
||
<imageobject>
|
||
<imagedata align="center" format="PNG" scale="100"
|
||
fileref="../images/pbds_pairing_priority_queue_text_modify_down_thin.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>
|
||
|
||
<!-- priority_queue 01 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
thin_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>thin_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
|
||
<!-- priority_queue 02 -->
|
||
<row>
|
||
<?dbhtml bgcolor="#B0B0B0" ?>
|
||
<entry namest="c1" nameend="c3">
|
||
pairing_heap
|
||
</entry>
|
||
</row>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>Tag</classname>
|
||
</entry>
|
||
<entry>
|
||
<classname>pairing_heap_tag</classname>
|
||
</entry>
|
||
</row>
|
||
|
||
</tbody>
|
||
</tgroup>
|
||
</informaltable>
|
||
|
||
|
||
</section>
|
||
|
||
<section xml:id="priority_queue.text_modify_down.observations">
|
||
<info><title>
|
||
Observations
|
||
</title></info>
|
||
|
||
<para>Most points in these results are similar to Priority Queue
|
||
Text <function>modify</function> Up Timing Test.</para>
|
||
|
||
<para>It is interesting to note, however, that as opposed to that
|
||
test, a thin heap (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>thin_heap_tag</classname>) is
|
||
outperformed by a pairing heap (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>pairing_heap_tag</classname>).
|
||
In this case, both heaps essentially perform an <function>erase</function>
|
||
operation followed by a <function>push</function> operation. As the other
|
||
tests show, a pairing heap is usually far more efficient than a
|
||
thin heap, so this is not surprising.</para>
|
||
<para>Most algorithms that involve priority queues increase values
|
||
(in the sense of the priority queue's comparison functor), and
|
||
so Priority Queue
|
||
Text <classname>modify</classname> Up Timing Test - is more interesting
|
||
than this test.</para>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
</section> <!-- priority_queue -->
|
||
|
||
<section xml:id="pbds.test.performance.observations">
|
||
<info><title>Observations</title></info>
|
||
|
||
<section xml:id="observations.associative">
|
||
<info><title>Associative</title></info>
|
||
|
||
<section xml:id="observations.associative.underlying">
|
||
<info><title>
|
||
Underlying Data-Structure Families
|
||
</title></info>
|
||
|
||
<para>In general, hash-based containers have better timing performance
|
||
than containers based on different underlying-data structures. The
|
||
main reason to choose a tree-based or trie-based container is if a
|
||
byproduct of the tree-like structure is required: either
|
||
order-preservation, or the ability to utilize node invariants. If
|
||
memory-use is the major factor, an ordered-vector tree gives
|
||
optimal results (albeit with high modificiation costs), and a
|
||
list-based container gives reasonable results.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="observations.associative.hash">
|
||
<info><title>
|
||
Hash-Based Containers
|
||
</title></info>
|
||
|
||
<para>Hash-based containers are typically either collision
|
||
chaining or probing. Collision-chaining
|
||
containers are more flexible internally, and so offer better
|
||
timing performance. Probing containers, if used for simple
|
||
value-types, manage memory more efficiently (they perform far
|
||
fewer allocation-related calls). In general, therefore, a
|
||
collision-chaining table should be used. A probing container,
|
||
conversely, might be used efficiently for operations such as
|
||
eliminating duplicates in a sequence, or counting the number of
|
||
occurrences within a sequence. Probing containers might be more
|
||
useful also in multithreaded applications where each thread
|
||
manipulates a hash-based container: in the standard, allocators have
|
||
class-wise semantics (see [meyers96more] - Item 10); a
|
||
probing container might incur less contention in this case.</para>
|
||
</section>
|
||
|
||
<section xml:id="observations.associative.hash_policies">
|
||
<info><title>
|
||
Hash Policies
|
||
</title></info>
|
||
|
||
<para>In hash-based containers, the range-hashing scheme seems to
|
||
affect performance more than other considerations. In most
|
||
settings, a mask-based scheme works well (or can be made to
|
||
work well). If the key-distribution can be estimated a-priori,
|
||
a simple hash function can produce nearly uniform hash-value
|
||
distribution. In many other cases (e.g., text hashing,
|
||
floating-point hashing), the hash function is powerful enough
|
||
to generate hash values with good uniformity properties
|
||
[knuth98sorting];
|
||
a modulo-based scheme, taking into account all bits of the hash
|
||
value, appears to overlap the hash function in its effort.</para>
|
||
<para>The range-hashing scheme determines many of the other
|
||
policies. A mask-based scheme works
|
||
well with an exponential-size policy; for
|
||
probing-based containers, it goes well with a linear-probe
|
||
function.</para>
|
||
<para>An orthogonal consideration is the trigger policy. This
|
||
presents difficult tradeoffs. E.g., different load
|
||
factors in a load-check trigger policy yield a
|
||
space/amortized-cost tradeoff.</para>
|
||
</section>
|
||
|
||
<section xml:id="observations.associative.branch">
|
||
<info><title>
|
||
Branch-Based Containers
|
||
</title></info>
|
||
<para>In general, there are several families of tree-based
|
||
underlying data structures: balanced node-based trees
|
||
(e.g., red-black or AVL trees), high-probability
|
||
balanced node-based trees (e.g., random treaps or
|
||
skip-lists), competitive node-based trees (e.g., splay
|
||
trees), vector-based "trees", and tries. (Additionally, there
|
||
are disk-residing or network-residing trees, such as B-Trees
|
||
and their numerous variants. An interface for this would have
|
||
to deal with the execution model and ACID guarantees; this is
|
||
out of the scope of this library.) Following are some
|
||
observations on their application to different settings.</para>
|
||
|
||
<para>Of the balanced node-based trees, this library includes a
|
||
red-black tree, as does standard (in
|
||
practice). This type of tree is the "workhorse" of tree-based
|
||
containers: it offers both reasonable modification and
|
||
reasonable lookup time. Unfortunately, this data structure
|
||
stores a huge amount of metadata. Each node must contain,
|
||
besides a value, three pointers and a boolean. This type might
|
||
be avoided if space is at a premium [austern00noset].</para>
|
||
<para>High-probability balanced node-based trees suffer the
|
||
drawbacks of deterministic balanced trees. Although they are
|
||
fascinating data structures, preliminary tests with them showed
|
||
their performance was worse than red-black trees. The library
|
||
does not contain any such trees, therefore.</para>
|
||
<para>Competitive node-based trees have two drawbacks. They are
|
||
usually somewhat unbalanced, and they perform a large number of
|
||
comparisons. Balanced trees perform one comparison per each
|
||
node they encounter on a search path; a splay tree performs two
|
||
comparisons. If the keys are complex objects, e.g.,
|
||
<classname>std::string</classname>, this can increase the running time.
|
||
Conversely, such trees do well when there is much locality of
|
||
reference. It is difficult to determine in which case to prefer
|
||
such trees over balanced trees. This library includes a splay
|
||
tree.</para>
|
||
<para>Ordered-vector trees use very little space
|
||
[austern00noset].
|
||
They do not have any other advantages (at least in this
|
||
implementation).</para>
|
||
<para>Large-fan-out PATRICIA tries have excellent lookup
|
||
performance, but they do so through maintaining, for each node,
|
||
a miniature "hash-table". Their space efficiency is low, and
|
||
their modification performance is bad. These tries might be
|
||
used for semi-static settings, where order preservation is
|
||
important. Alternatively, red-black trees cross-referenced with
|
||
hash tables can be used. [okasaki98mereable]
|
||
discusses small-fan-out PATRICIA tries for integers, but the
|
||
cited results seem to indicate that the amortized cost of
|
||
maintaining such trees is higher than that of balanced trees.
|
||
Moderate-fan-out trees might be useful for sequences where each
|
||
element has a limited number of choices, e.g., DNA
|
||
strings.</para>
|
||
</section>
|
||
|
||
<section xml:id="observations.associative.mapping_semantics">
|
||
<info><title>
|
||
Mapping-Semantics
|
||
</title></info>
|
||
<para>Different mapping semantics were discussed in the introduction and design sections.Here
|
||
the focus will be on the case where a keys can be composed into
|
||
primary keys and secondary keys. (In the case where some keys
|
||
are completely identical, it is trivial that one should use an
|
||
associative container mapping values to size types.) In this
|
||
case there are (at least) five possibilities:</para>
|
||
<orderedlist>
|
||
<listitem><para>Use an associative container that allows equivalent-key
|
||
values (such as <classname>std::multimap</classname>)</para></listitem>
|
||
<listitem><para>Use a unique-key value associative container that maps
|
||
each primary key to some complex associative container of
|
||
secondary keys, say a tree-based or hash-based container.
|
||
</para></listitem>
|
||
<listitem><para>Use a unique-key value associative container that maps
|
||
each primary key to some simple associative container of
|
||
secondary keys, say a list-based container.</para></listitem>
|
||
<listitem><para>Use a unique-key value associative container that maps
|
||
each primary key to some non-associative container
|
||
(e.g., <classname>std::vector</classname>)</para></listitem>
|
||
<listitem><para>Use a unique-key value associative container that takes
|
||
into account both primary and secondary keys.</para></listitem>
|
||
</orderedlist>
|
||
<para>Stated simply: there is a simple answer for this. (Excluding
|
||
option 1, which should be avoided in all cases).</para>
|
||
<para>If the expected ratio of secondary keys to primary keys is
|
||
small, then 3 and 4 seem reasonable. Both types of secondary
|
||
containers are relatively lightweight (in terms of memory use
|
||
and construction time), and so creating an entire container
|
||
object for each primary key is not too expensive. Option 4
|
||
might be preferable to option 3 if changing the secondary key
|
||
of some primary key is frequent - one cannot modify an
|
||
associative container's key, and the only possibility,
|
||
therefore, is erasing the secondary key and inserting another
|
||
one instead; a non-associative container, conversely, can
|
||
support in-place modification. The actual cost of erasing a
|
||
secondary key and inserting another one depends also on the
|
||
allocator used for secondary associative-containers (The tests
|
||
above used the standard allocator, but in practice one might
|
||
choose to use, e.g., [boost_pool]). Option 2 is
|
||
definitely an overkill in this case. Option 1 loses out either
|
||
immediately (when there is one secondary key per primary key)
|
||
or almost immediately after that. Option 5 has the same
|
||
drawbacks as option 2, but it has the additional drawback that
|
||
finding all values whose primary key is equivalent to some key,
|
||
might be linear in the total number of values stored (for
|
||
example, if using a hash-based container).</para>
|
||
<para>If the expected ratio of secondary keys to primary keys is
|
||
large, then the answer is more complicated. It depends on the
|
||
distribution of secondary keys to primary keys, the
|
||
distribution of accesses according to primary keys, and the
|
||
types of operations most frequent.</para>
|
||
<para>To be more precise, assume there are m primary keys,
|
||
primary key i is mapped to n<subscript>i</subscript>
|
||
secondary keys, and each primary key is mapped, on average, to
|
||
n secondary keys (i.e.,
|
||
E(n<subscript>i</subscript>) = n).</para>
|
||
<para>Suppose one wants to find a specific pair of primary and
|
||
secondary keys. Using 1 with a tree based container
|
||
(<classname>std::multimap</classname>), the expected cost is
|
||
E(Θ(log(m) + n<subscript>i</subscript>)) = Θ(log(m) +
|
||
n); using 1 with a hash-based container
|
||
(<classname>std::tr1::unordered_multimap</classname>), the expected cost is
|
||
Θ(n). Using 2 with a primary hash-based container
|
||
and secondary hash-based containers, the expected cost is
|
||
O(1); using 2 with a primary tree-based container and
|
||
secondary tree-based containers, the expected cost is (using
|
||
the Jensen inequality [motwani95random])
|
||
E(O(log(m) + log(n<subscript>i</subscript>)) = O(log(m)) +
|
||
E(O(log(n<subscript>i</subscript>)) = O(log(m)) + O(log(n)),
|
||
assuming that primary keys are accessed equiprobably. 3 and 4
|
||
are similar to 1, but with lower constants. Using 5 with a
|
||
hash-based container, the expected cost is O(1); using 5
|
||
with a tree based container, the cost is
|
||
E(Θ(log(mn))) = Θ(log(m) +
|
||
log(n)).</para>
|
||
<para>Suppose one needs the values whose primary key matches some
|
||
given key. Using 1 with a hash-based container, the expected
|
||
cost is Θ(n), but the values will not be ordered
|
||
by secondary keys (which may or may not be required); using 1
|
||
with a tree-based container, the expected cost is
|
||
Θ(log(m) + n), but with high constants; again the
|
||
values will not be ordered by secondary keys. 2, 3, and 4 are
|
||
similar to 1, but typically with lower constants (and,
|
||
additionally, if one uses a tree-based container for secondary
|
||
keys, they will be ordered). Using 5 with a hash-based
|
||
container, the cost is Θ(mn).</para>
|
||
<para>Suppose one wants to assign to a primary key all secondary
|
||
keys assigned to a different primary key. Using 1 with a
|
||
hash-based container, the expected cost is Θ(n),
|
||
but with very high constants; using 1 with a tree-based
|
||
container, the cost is Θ(nlog(mn)). Using 2, 3,
|
||
and 4, the expected cost is Θ(n), but typically
|
||
with far lower costs than 1. 5 is similar to 1.</para>
|
||
|
||
</section>
|
||
|
||
</section>
|
||
|
||
|
||
<section xml:id="observations.priority_queue">
|
||
<info><title>Priority_Queue</title></info>
|
||
|
||
<section xml:id="observations.priority_queue.complexity">
|
||
<info><title>Complexity</title></info>
|
||
|
||
<para>The following table shows the complexities of the different
|
||
underlying data structures in terms of orders of growth. It is
|
||
interesting to note that this table implies something about the
|
||
constants of the operations as well (see Amortized <function>push</function>
|
||
and <function>pop</function> operations).</para>
|
||
|
||
<informaltable frame="all">
|
||
|
||
<tgroup cols="6" align="left" colsep="1" rowsep="1">
|
||
<colspec colname="c1"/>
|
||
<colspec colname="c2"/>
|
||
<colspec colname="c3"/>
|
||
<colspec colname="c4"/>
|
||
<colspec colname="c5"/>
|
||
<colspec colname="c6"/>
|
||
<thead>
|
||
<row>
|
||
<entry></entry>
|
||
<entry><emphasis><function>push</function></emphasis></entry>
|
||
<entry><emphasis><function>pop</function></emphasis></entry>
|
||
<entry><emphasis><function>modify</function></emphasis></entry>
|
||
<entry><emphasis><function>erase</function></emphasis></entry>
|
||
<entry><emphasis><function>join</function></emphasis></entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
|
||
<row>
|
||
<entry>
|
||
<classname>std::priority_queue</classname>
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n)) Worst
|
||
</entry>
|
||
<entry>
|
||
Θ(n log(n)) Worst
|
||
<subscript>[std note 1]</subscript>
|
||
</entry>
|
||
<entry>
|
||
Θ(n log(n))
|
||
<subscript>[std note 2]</subscript>
|
||
</entry>
|
||
<entry>
|
||
Θ(n log(n))
|
||
<subscript>[std note 1]</subscript>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
<<classname>Tag</classname> =
|
||
<classname>pairing_heap_tag</classname>>
|
||
</entry>
|
||
<entry>
|
||
O(1)
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
O(1)
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
<<classname>Tag</classname> =
|
||
<classname>binary_heap_tag</classname>>
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(n)
|
||
</entry>
|
||
<entry>
|
||
Θ(n)
|
||
</entry>
|
||
<entry>
|
||
Θ(n)
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
<<classname>Tag</classname> =
|
||
<classname>binomial_heap_tag</classname>>
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n)) worst
|
||
O(1) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname>
|
||
<<classname>Tag</classname> =
|
||
<classname>rc_binomial_heap_tag</classname>>
|
||
</entry>
|
||
<entry>
|
||
O(1)
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n))
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry>
|
||
<classname>priority_queue</classname><<classname>Tag</classname> =
|
||
<classname>thin_heap_tag</classname>>
|
||
</entry>
|
||
<entry>
|
||
O(1)
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(log(n)) worst
|
||
O(1) amortized,
|
||
or Θ(log(n)) amortized
|
||
<subscript>[thin_heap_note]</subscript>
|
||
</entry>
|
||
<entry>
|
||
Θ(n) worst
|
||
Θ(log(n)) amortized
|
||
</entry>
|
||
<entry>
|
||
Θ(n)
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
|
||
</informaltable>
|
||
|
||
<para>[std note 1] This
|
||
is not a property of the algorithm, but rather due to the fact
|
||
that the standard's priority queue implementation does not support
|
||
iterators (and consequently the ability to access a specific
|
||
value inside it). If the priority queue is adapting an
|
||
<classname>std::vector</classname>, then it is still possible to reduce this
|
||
to Θ(n) by adapting over the standard's adapter and
|
||
using the fact that <function>top</function> returns a reference to the
|
||
first value; if, however, it is adapting an
|
||
<classname>std::deque</classname>, then this is impossible.</para>
|
||
|
||
<para>[std note 2] As
|
||
with [std note 1], this is not a
|
||
property of the algorithm, but rather the standard's implementation.
|
||
Again, if the priority queue is adapting an
|
||
<classname>std::vector</classname> then it is possible to reduce this to
|
||
Θ(n), but with a very high constant (one must call
|
||
<function>std::make_heap</function> which is an expensive linear
|
||
operation); if the priority queue is adapting an
|
||
<classname>std::deque</classname>, then this is impossible.</para>
|
||
|
||
<para>[thin_heap_note] A thin heap has
|
||
Θ(log(n)) worst case <function>modify</function> time
|
||
always, but the amortized time depends on the nature of the
|
||
operation: I) if the operation increases the key (in the sense
|
||
of the priority queue's comparison functor), then the amortized
|
||
time is O(1), but if II) it decreases it, then the
|
||
amortized time is the same as the worst case time. Note that
|
||
for most algorithms, I) is important and II) is not.</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="observations.priority_queue.amortized_ops">
|
||
<info><title>
|
||
Amortized <function>push</function>
|
||
and <function>pop</function> operations
|
||
</title></info>
|
||
|
||
|
||
<para>In many cases, a priority queue is needed primarily for
|
||
sequences of <function>push</function> and <function>pop</function> operations. All of
|
||
the underlying data structures have the same amortized
|
||
logarithmic complexity, but they differ in terms of
|
||
constants.</para>
|
||
<para>The table above shows that the different data structures are
|
||
"constrained" in some respects. In general, if a data structure
|
||
has lower worst-case complexity than another, then it will
|
||
perform slower in the amortized sense. Thus, for example a
|
||
redundant-counter binomial heap (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>rc_binomial_heap_tag</classname>)
|
||
has lower worst-case <function>push</function> performance than a binomial
|
||
heap (<classname>priority_queue</classname>
|
||
with <classname>Tag</classname> = <classname>binomial_heap_tag</classname>),
|
||
and so its amortized <function>push</function> performance is slower in
|
||
terms of constants.</para>
|
||
<para>As the table shows, the "least constrained" underlying
|
||
data structures are binary heaps and pairing heaps.
|
||
Consequently, it is not surprising that they perform best in
|
||
terms of amortized constants.</para>
|
||
<orderedlist>
|
||
<listitem><para>Pairing heaps seem to perform best for non-primitive
|
||
types (e.g., <classname>std::string</classname>s), as shown by
|
||
Priority
|
||
Queue Text <function>push</function> Timing Test and Priority
|
||
Queue Text <function>push</function> and <function>pop</function> Timing
|
||
Test</para></listitem>
|
||
<listitem><para>binary heaps seem to perform best for primitive types
|
||
(e.g., <type>int</type>s), as shown by Priority
|
||
Queue Random Integer <function>push</function> Timing Test and
|
||
Priority
|
||
Queue Random Integer <function>push</function> and <function>pop</function> Timing
|
||
Test.</para></listitem>
|
||
</orderedlist>
|
||
|
||
</section>
|
||
|
||
<section xml:id="observations.priority_queue.graphs">
|
||
<info><title>
|
||
Graph Algorithms
|
||
</title></info>
|
||
|
||
<para>In some graph algorithms, a decrease-key operation is
|
||
required [clrs2001];
|
||
this operation is identical to <function>modify</function> if a value is
|
||
increased (in the sense of the priority queue's comparison
|
||
functor). The table above and Priority Queue
|
||
Text <function>modify</function> Up Timing Test show that a thin heap
|
||
(<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>thin_heap_tag</classname>)
|
||
outperforms a pairing heap (<classname>priority_queue</classname> with
|
||
<classname>Tag</classname> = <classname>Tag</classname> = <classname>pairing_heap_tag</classname>),
|
||
but the rest of the tests show otherwise.</para>
|
||
|
||
<para>This makes it difficult to decide which implementation to use in
|
||
this case. Dijkstra's shortest-path algorithm, for example, requires
|
||
Θ(n) <function>push</function> and <function>pop</function> operations
|
||
(in the number of vertices), but O(n<superscript>2</superscript>)
|
||
<function>modify</function> operations, which can be in practice Θ(n)
|
||
as well. It is difficult to find an a-priori characterization of
|
||
graphs in which the actual number of <function>modify</function>
|
||
operations will dwarf the number of <function>push</function> and
|
||
<function>pop</function> operations.</para>
|
||
|
||
</section>
|
||
|
||
</section> <!-- priority_queue -->
|
||
|
||
</section>
|
||
|
||
|
||
</section> <!-- performance -->
|
||
|
||
</section> |