• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<html>
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5<title>Performance</title>
6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
9<link rel="up" href="../intrusive.html" title="Chapter 19. Boost.Intrusive">
10<link rel="prev" href="design_notes.html" title="Design Notes">
11<link rel="next" href="release_notes.html" title="Release Notes">
12</head>
13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
14<table cellpadding="2" width="100%"><tr>
15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
16<td align="center"><a href="../../../index.html">Home</a></td>
17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
20<td align="center"><a href="../../../more/index.htm">More</a></td>
21</tr></table>
22<hr>
23<div class="spirit-nav">
24<a accesskey="p" href="design_notes.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../intrusive.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="release_notes.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
25</div>
26<div class="section">
27<div class="titlepage"><div><div><h2 class="title" style="clear: both">
28<a name="intrusive.performance"></a><a class="link" href="performance.html" title="Performance">Performance</a>
29</h2></div></div></div>
30<div class="toc"><dl class="toc">
31<dt><span class="section"><a href="performance.html#intrusive.performance.performance_results_push_back">Back
32      insertion and destruction</a></span></dt>
33<dt><span class="section"><a href="performance.html#intrusive.performance.performance_results_reversing">Reversing</a></span></dt>
34<dt><span class="section"><a href="performance.html#intrusive.performance.performance_results_sorting">Sorting</a></span></dt>
35<dt><span class="section"><a href="performance.html#intrusive.performance.performance_results_write_access">Write
36      access</a></span></dt>
37<dt><span class="section"><a href="performance.html#intrusive.performance.performance_results_conclusions">Conclusions</a></span></dt>
38</dl></div>
39<p>
40      <span class="bold"><strong>Boost.Intrusive</strong></span> containers offer speed improvements
41      compared to non-intrusive containers primarily because:
42    </p>
43<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
44<li class="listitem">
45          They minimize memory allocation/deallocation calls.
46        </li>
47<li class="listitem">
48          They obtain better memory locality.
49        </li>
50</ul></div>
51<p>
52      This section will show performance tests comparing some operations on <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive</span><span class="special">::</span><span class="identifier">list</span></code> and
53      <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span></code>:
54    </p>
55<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
56<li class="listitem">
57          Insertions using <code class="computeroutput"><span class="identifier">push_back</span></code>
58          and container destruction will show the overhead associated with memory
59          allocation/deallocation.
60        </li>
61<li class="listitem">
62          The <code class="computeroutput"><span class="identifier">reverse</span></code> member function
63          will show the advantages of the compact memory representation that can
64          be achieved with intrusive containers.
65        </li>
66<li class="listitem">
67          The <code class="computeroutput"><span class="identifier">sort</span></code> and <code class="computeroutput"><span class="identifier">write</span> <span class="identifier">access</span></code>
68          tests will show the advantage of intrusive containers minimizing memory
69          accesses compared to containers of pointers.
70        </li>
71</ul></div>
72<p>
73      Given an object of type <code class="computeroutput"><span class="identifier">T</span></code>,
74      <code class="computeroutput"><a class="link" href="../boost/intrusive/list.html" title="Class template list">boost::intrusive::list&lt;T&gt;</a></code>
75      can replace <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> to
76      avoid memory allocation overhead, or it can replace <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">*&gt;</span></code> when
77      the user wants containers with polymorphic values or wants to share values
78      between several containers. Because of this versatility, the performance tests
79      will be executed for 6 different list types:
80    </p>
81<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
82<li class="listitem">
83          3 intrusive lists holding a class named <code class="computeroutput"><span class="identifier">itest_class</span></code>,
84          each one with a different linking policy (<code class="computeroutput"><span class="identifier">normal_link</span></code>,
85          <code class="computeroutput"><span class="identifier">safe_link</span></code>, <code class="computeroutput"><span class="identifier">auto_unlink</span></code>). The <code class="computeroutput"><span class="identifier">itest_class</span></code>
86          objects will be tightly packed in a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">itest_class</span><span class="special">&gt;</span></code> object.
87        </li>
88<li class="listitem">
89          <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">test_class</span><span class="special">&gt;</span></code>,
90          where <code class="computeroutput"><span class="identifier">test_class</span></code> is exactly
91          the same as <code class="computeroutput"><span class="identifier">itest_class</span></code>,
92          but without the intrusive hook.
93        </li>
94<li class="listitem">
95          <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">test_class</span><span class="special">*&gt;</span></code>.
96          The list will contain pointers to <code class="computeroutput"><span class="identifier">test_class</span></code>
97          objects tightly packed in a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="identifier">test_class</span><span class="special">&gt;</span></code> object. We'll call this configuration
98          <span class="emphasis"><em>compact pointer list</em></span>
99        </li>
100<li class="listitem">
101          <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">test_class</span><span class="special">*&gt;</span></code>.
102          The list will contain pointers to <code class="computeroutput"><span class="identifier">test_class</span></code>
103          objects owned by a <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span><span class="special">&lt;</span><span class="identifier">test_class</span><span class="special">&gt;</span></code> object. We'll call this configuration
104          <span class="emphasis"><em>disperse pointer list</em></span>.
105        </li>
106</ul></div>
107<p>
108      Both <code class="computeroutput"><span class="identifier">test_class</span></code> and <code class="computeroutput"><span class="identifier">itest_class</span></code> are templatized classes that
109      can be configured with a boolean to increase the size of the object. This way,
110      the tests can be executed with small and big objects. Here is the first part
111      of the testing code, which shows the definitions of <code class="computeroutput"><span class="identifier">test_class</span></code>
112      and <code class="computeroutput"><span class="identifier">itest_class</span></code> classes, and
113      some other utilities:
114    </p>
115<pre class="programlisting"><span class="comment">//Iteration and element count defines</span>
116<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">NumIter</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>
117<span class="keyword">const</span> <span class="keyword">int</span> <span class="identifier">NumElements</span>   <span class="special">=</span> <span class="number">50000</span><span class="special">;</span>
118
119<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">intrusive</span><span class="special">;</span>
120
121<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">bool</span> <span class="identifier">BigSize</span><span class="special">&gt;</span>  <span class="keyword">struct</span> <span class="identifier">filler</span>        <span class="special">{</span>  <span class="keyword">int</span> <span class="identifier">dummy</span><span class="special">[</span><span class="number">10</span><span class="special">];</span>   <span class="special">};</span>
122<span class="keyword">template</span> <span class="special">&lt;&gt;</span>             <span class="keyword">struct</span> <span class="identifier">filler</span><span class="special">&lt;</span><span class="keyword">false</span><span class="special">&gt;</span> <span class="special">{};</span>
123
124<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">bool</span> <span class="identifier">BigSize</span><span class="special">&gt;</span> <span class="comment">//The object for non-intrusive containers</span>
125<span class="keyword">struct</span> <span class="identifier">test_class</span> <span class="special">:</span>  <span class="keyword">private</span> <span class="identifier">filler</span><span class="special">&lt;</span><span class="identifier">BigSize</span><span class="special">&gt;</span>
126<span class="special">{</span>
127   <span class="keyword">int</span> <span class="identifier">i_</span><span class="special">;</span>
128   <span class="identifier">test_class</span><span class="special">()</span>               <span class="special">{}</span>
129   <span class="identifier">test_class</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">:</span>  <span class="identifier">i_</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span> <span class="special">{}</span>
130   <span class="keyword">friend</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&lt;(</span><span class="keyword">const</span> <span class="identifier">test_class</span> <span class="special">&amp;</span><span class="identifier">l</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">test_class</span> <span class="special">&amp;</span><span class="identifier">r</span><span class="special">)</span>  <span class="special">{</span>  <span class="keyword">return</span> <span class="identifier">l</span><span class="special">.</span><span class="identifier">i_</span> <span class="special">&lt;</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">i_</span><span class="special">;</span>  <span class="special">}</span>
131   <span class="keyword">friend</span> <span class="keyword">bool</span> <span class="keyword">operator</span> <span class="special">&gt;(</span><span class="keyword">const</span> <span class="identifier">test_class</span> <span class="special">&amp;</span><span class="identifier">l</span><span class="special">,</span> <span class="keyword">const</span> <span class="identifier">test_class</span> <span class="special">&amp;</span><span class="identifier">r</span><span class="special">)</span>  <span class="special">{</span>  <span class="keyword">return</span> <span class="identifier">l</span><span class="special">.</span><span class="identifier">i_</span> <span class="special">&gt;</span> <span class="identifier">r</span><span class="special">.</span><span class="identifier">i_</span><span class="special">;</span>  <span class="special">}</span>
132<span class="special">};</span>
133
134<span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">bool</span> <span class="identifier">BigSize</span><span class="special">,</span> <span class="identifier">link_mode_type</span> <span class="identifier">LinkMode</span><span class="special">&gt;</span>
135<span class="keyword">struct</span> <span class="identifier">itest_class</span>   <span class="comment">//The object for intrusive containers</span>
136   <span class="special">:</span>  <span class="keyword">public</span> <span class="identifier">list_base_hook</span><span class="special">&lt;</span><span class="identifier">link_mode</span><span class="special">&lt;</span><span class="identifier">LinkMode</span><span class="special">&gt;</span> <span class="special">&gt;,</span>  <span class="keyword">public</span> <span class="identifier">test_class</span><span class="special">&lt;</span><span class="identifier">BigSize</span><span class="special">&gt;</span>
137<span class="special">{</span>
138   <span class="identifier">itest_class</span><span class="special">()</span>                                <span class="special">{}</span>
139   <span class="identifier">itest_class</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span><span class="special">)</span> <span class="special">:</span> <span class="identifier">test_class</span><span class="special">&lt;</span><span class="identifier">BigSize</span><span class="special">&gt;(</span><span class="identifier">i</span><span class="special">)</span>  <span class="special">{}</span>
140<span class="special">};</span>
141
142<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">FuncObj</span><span class="special">&gt;</span> <span class="comment">//Adapts functors taking values to functors taking pointers</span>
143<span class="keyword">struct</span> <span class="identifier">func_ptr_adaptor</span>  <span class="special">:</span>  <span class="keyword">public</span> <span class="identifier">FuncObj</span>
144<span class="special">{</span>
145   <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">FuncObj</span><span class="special">::</span><span class="identifier">first_argument_type</span><span class="special">*</span>  <span class="identifier">first_argument_type</span><span class="special">;</span>
146   <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">FuncObj</span><span class="special">::</span><span class="identifier">second_argument_type</span><span class="special">*</span> <span class="identifier">second_argument_type</span><span class="special">;</span>
147   <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">FuncObj</span><span class="special">::</span><span class="identifier">result_type</span>           <span class="identifier">result_type</span><span class="special">;</span>
148   <span class="identifier">result_type</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">first_argument_type</span> <span class="identifier">a</span><span class="special">,</span>  <span class="identifier">second_argument_type</span> <span class="identifier">b</span><span class="special">)</span> <span class="keyword">const</span>
149      <span class="special">{</span>  <span class="keyword">return</span> <span class="identifier">FuncObj</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()(*</span><span class="identifier">a</span><span class="special">,</span> <span class="special">*</span><span class="identifier">b</span><span class="special">);</span> <span class="special">}</span>
150<span class="special">};</span>
151</pre>
152<p>
153      As we can see, <code class="computeroutput"><span class="identifier">test_class</span></code> is
154      a very simple class holding an <code class="computeroutput"><span class="keyword">int</span></code>.
155      <code class="computeroutput"><span class="identifier">itest_class</span></code> is just a class
156      that has a base hook (<code class="computeroutput"><a class="link" href="../boost/intrusive/list_base_hook.html" title="Class template list_base_hook">list_base_hook</a></code>)
157      and also derives from <code class="computeroutput"><span class="identifier">test_class</span></code>.
158    </p>
159<p>
160      <code class="computeroutput"><span class="identifier">func_ptr_adaptor</span></code> is just a
161      functor adaptor to convert function objects taking <code class="computeroutput"><span class="identifier">test_list</span></code>
162      objects to function objects taking pointers to them.
163    </p>
164<p>
165      You can find the full test code in the <a href="../../../libs/intrusive/perf/perf_list.cpp" target="_top">perf_list.cpp</a>
166      source file.
167    </p>
168<div class="section">
169<div class="titlepage"><div><div><h3 class="title">
170<a name="intrusive.performance.performance_results_push_back"></a><a class="link" href="performance.html#intrusive.performance.performance_results_push_back" title="Back insertion and destruction">Back
171      insertion and destruction</a>
172</h3></div></div></div>
173<p>
174        The first test will measure the benefits we can obtain with intrusive containers
175        avoiding memory allocations and deallocations. All the objects to be inserted
176        in intrusive containers are allocated in a single allocation call, whereas
177        <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">list</span></code> will need to allocate memory for each
178        object and deallocate it for every erasure (or container destruction).
179      </p>
180<p>
181        Let's compare the code to be executed for each container type for different
182        insertion tests:
183      </p>
184<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">ilist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;</span> <span class="identifier">objects</span><span class="special">(</span><span class="identifier">NumElements</span><span class="special">);</span>
185<span class="identifier">ilist</span> <span class="identifier">l</span><span class="special">;</span>
186<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumElements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
187   <span class="identifier">l</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">objects</span><span class="special">[</span><span class="identifier">i</span><span class="special">]);</span>
188<span class="comment">//Elements are unlinked in ilist's destructor</span>
189<span class="comment">//Elements are destroyed in vector's destructor</span>
190</pre>
191<p>
192        For intrusive containers, all the values are created in a vector and after
193        that inserted in the intrusive list.
194      </p>
195<pre class="programlisting"><span class="identifier">stdlist</span> <span class="identifier">l</span><span class="special">;</span>
196<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumElements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
197   <span class="identifier">l</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">(</span><span class="identifier">i</span><span class="special">));</span>
198<span class="comment">//Elements unlinked and destroyed in stdlist's destructor</span>
199</pre>
200<p>
201        For a standard list, elements are pushed back using push_back().
202      </p>
203<pre class="programlisting"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;</span> <span class="identifier">objects</span><span class="special">(</span><span class="identifier">NumElements</span><span class="special">);</span>
204<span class="identifier">stdptrlist</span> <span class="identifier">l</span><span class="special">;</span>
205<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumElements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">)</span>
206   <span class="identifier">l</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(&amp;</span><span class="identifier">objects</span><span class="special">[</span><span class="identifier">i</span><span class="special">]);</span>
207<span class="comment">//Pointers to elements unlinked and destroyed in stdptrlist's destructor</span>
208<span class="comment">//Elements destroyed in vector's destructor</span>
209</pre>
210<p>
211        For a standard compact pointer list, elements are created in a vector and
212        pushed back in the pointer list using push_back().
213      </p>
214<pre class="programlisting"><span class="identifier">stdlist</span> <span class="identifier">objects</span><span class="special">;</span>  <span class="identifier">stdptrlist</span> <span class="identifier">l</span><span class="special">;</span>
215<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumElements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
216   <span class="identifier">objects</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="keyword">typename</span> <span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">(</span><span class="identifier">i</span><span class="special">));</span>
217   <span class="identifier">l</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(&amp;</span><span class="identifier">objects</span><span class="special">.</span><span class="identifier">back</span><span class="special">());</span>
218<span class="special">}</span>
219<span class="comment">//Pointers to elements unlinked and destroyed in stdptrlist's destructor</span>
220<span class="comment">//Elements unlinked and destroyed in stdlist's destructor</span>
221</pre>
222<p>
223        For a <span class="emphasis"><em>disperse pointer list</em></span>, elements are created in
224        a list and pushed back in the pointer list using push_back().
225      </p>
226<p>
227        These are the times in microseconds for each case, and the normalized time:
228      </p>
229<div class="table">
230<a name="intrusive.performance.performance_results_push_back.back_insertion_destruction_times"></a><p class="title"><b>Table 19.2. Back insertion + destruction times for Visual C++ 7.1 / Windows XP</b></p>
231<div class="table-contents"><table class="table" summary="Back insertion + destruction times for Visual C++ 7.1 / Windows XP">
232<colgroup>
233<col>
234<col>
235<col>
236</colgroup>
237<thead><tr>
238<th>
239                <p>
240                  Container
241                </p>
242              </th>
243<th>
244                <p>
245                  Time in us/iteration (small object / big object)
246                </p>
247              </th>
248<th>
249                <p>
250                  Normalized time (small object / big object)
251                </p>
252              </th>
253</tr></thead>
254<tbody>
255<tr>
256<td>
257                <p>
258                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
259                  list
260                </p>
261              </td>
262<td>
263                <p>
264                  5000 / 22500
265                </p>
266              </td>
267<td>
268                <p>
269                  1 / 1
270                </p>
271              </td>
272</tr>
273<tr>
274<td>
275                <p>
276                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
277                  list
278                </p>
279              </td>
280<td>
281                <p>
282                  7812 / 32187
283                </p>
284              </td>
285<td>
286                <p>
287                  1.56 / 1.43
288                </p>
289              </td>
290</tr>
291<tr>
292<td>
293                <p>
294                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
295                  list
296                </p>
297              </td>
298<td>
299                <p>
300                  10156 / 41562
301                </p>
302              </td>
303<td>
304                <p>
305                  2.03 / 1.84
306                </p>
307              </td>
308</tr>
309<tr>
310<td>
311                <p>
312                  Standard list
313                </p>
314              </td>
315<td>
316                <p>
317                  26875 / 97500
318                </p>
319              </td>
320<td>
321                <p>
322                  5.37 / 4.33
323                </p>
324              </td>
325</tr>
326<tr>
327<td>
328                <p>
329                  Standard compact pointer list
330                </p>
331              </td>
332<td>
333                <p>
334                  76406 / 86718
335                </p>
336              </td>
337<td>
338                <p>
339                  15.28 / 3.85
340                </p>
341              </td>
342</tr>
343<tr>
344<td>
345                <p>
346                  Standard disperse pointer list
347                </p>
348              </td>
349<td>
350                <p>
351                  146562 / 175625
352                </p>
353              </td>
354<td>
355                <p>
356                  29.31 / 7.80
357                </p>
358              </td>
359</tr>
360</tbody>
361</table></div>
362</div>
363<br class="table-break"><div class="table">
364<a name="intrusive.performance.performance_results_push_back.back_insertion_destruction_time0"></a><p class="title"><b>Table 19.3. Back insertion + destruction times for GCC 4.1.1 / MinGW over Windows
365        XP</b></p>
366<div class="table-contents"><table class="table" summary="Back insertion + destruction times for GCC 4.1.1 / MinGW over Windows
367        XP">
368<colgroup>
369<col>
370<col>
371<col>
372</colgroup>
373<thead><tr>
374<th>
375                <p>
376                  Container
377                </p>
378              </th>
379<th>
380                <p>
381                  Time in us/iteration (small object / big object)
382                </p>
383              </th>
384<th>
385                <p>
386                  Normalized time (small object / big object)
387                </p>
388              </th>
389</tr></thead>
390<tbody>
391<tr>
392<td>
393                <p>
394                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
395                  list
396                </p>
397              </td>
398<td>
399                <p>
400                  4375 / 22187
401                </p>
402              </td>
403<td>
404                <p>
405                  1 / 1
406                </p>
407              </td>
408</tr>
409<tr>
410<td>
411                <p>
412                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
413                  list
414                </p>
415              </td>
416<td>
417                <p>
418                  7812 / 32812
419                </p>
420              </td>
421<td>
422                <p>
423                  1.78 / 1.47
424                </p>
425              </td>
426</tr>
427<tr>
428<td>
429                <p>
430                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
431                  list
432                </p>
433              </td>
434<td>
435                <p>
436                  10468 / 42031
437                </p>
438              </td>
439<td>
440                <p>
441                  2.39 / 1.89
442                </p>
443              </td>
444</tr>
445<tr>
446<td>
447                <p>
448                  Standard list
449                </p>
450              </td>
451<td>
452                <p>
453                  81250 / 98125
454                </p>
455              </td>
456<td>
457                <p>
458                  18.57 / 4.42
459                </p>
460              </td>
461</tr>
462<tr>
463<td>
464                <p>
465                  Standard compact pointer list
466                </p>
467              </td>
468<td>
469                <p>
470                  83750 / 94218
471                </p>
472              </td>
473<td>
474                <p>
475                  19.14 / 4.24
476                </p>
477              </td>
478</tr>
479<tr>
480<td>
481                <p>
482                  Standard disperse pointer list
483                </p>
484              </td>
485<td>
486                <p>
487                  155625 / 175625
488                </p>
489              </td>
490<td>
491                <p>
492                  35.57 / 7.91
493                </p>
494              </td>
495</tr>
496</tbody>
497</table></div>
498</div>
499<br class="table-break"><div class="table">
500<a name="intrusive.performance.performance_results_push_back.back_insertion_destruction_time1"></a><p class="title"><b>Table 19.4. Back insertion + destruction times for GCC 4.1.2 / Linux Kernel 2.6.18
501        (OpenSuse 10.2)</b></p>
502<div class="table-contents"><table class="table" summary="Back insertion + destruction times for GCC 4.1.2 / Linux Kernel 2.6.18
503        (OpenSuse 10.2)">
504<colgroup>
505<col>
506<col>
507<col>
508</colgroup>
509<thead><tr>
510<th>
511                <p>
512                  Container
513                </p>
514              </th>
515<th>
516                <p>
517                  Time in us/iteration (small object / big object)
518                </p>
519              </th>
520<th>
521                <p>
522                  Normalized time (small object / big object)
523                </p>
524              </th>
525</tr></thead>
526<tbody>
527<tr>
528<td>
529                <p>
530                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
531                  list
532                </p>
533              </td>
534<td>
535                <p>
536                  4792 / 20495
537                </p>
538              </td>
539<td>
540                <p>
541                  1 / 1
542                </p>
543              </td>
544</tr>
545<tr>
546<td>
547                <p>
548                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
549                  list
550                </p>
551              </td>
552<td>
553                <p>
554                  7709 / 30803
555                </p>
556              </td>
557<td>
558                <p>
559                  1.60 / 1.5
560                </p>
561              </td>
562</tr>
563<tr>
564<td>
565                <p>
566                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
567                  list
568                </p>
569              </td>
570<td>
571                <p>
572                  10180 / 41183
573                </p>
574              </td>
575<td>
576                <p>
577                  2.12 / 2.0
578                </p>
579              </td>
580</tr>
581<tr>
582<td>
583                <p>
584                  Standard list
585                </p>
586              </td>
587<td>
588                <p>
589                  17031 / 32586
590                </p>
591              </td>
592<td>
593                <p>
594                  3.55 / 1.58
595                </p>
596              </td>
597</tr>
598<tr>
599<td>
600                <p>
601                  Standard compact pointer list
602                </p>
603              </td>
604<td>
605                <p>
606                  27221 / 34823
607                </p>
608              </td>
609<td>
610                <p>
611                  5.68 / 1.69
612                </p>
613              </td>
614</tr>
615<tr>
616<td>
617                <p>
618                  Standard disperse pointer list
619                </p>
620              </td>
621<td>
622                <p>
623                  102272 / 60056
624                </p>
625              </td>
626<td>
627                <p>
628                  21.34 / 2.93
629                </p>
630              </td>
631</tr>
632</tbody>
633</table></div>
634</div>
635<br class="table-break"><p>
636        The results are logical: intrusive lists just need one allocation. The destruction
637        time of the <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
638        container is trivial (complexity: <code class="computeroutput"><span class="identifier">O</span><span class="special">(</span><span class="number">1</span><span class="special">)</span></code>),
639        whereas <code class="computeroutput"><span class="identifier">safe_link</span></code> and <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive containers need to
640        put the hooks of erased values in the default state (complexity: <code class="computeroutput"><span class="identifier">O</span><span class="special">(</span><span class="identifier">NumElements</span><span class="special">)</span></code>). That's why <code class="computeroutput"><span class="identifier">normal_link</span></code>
641        intrusive list shines in this test.
642      </p>
643<p>
644        Non-intrusive containers need to make many more allocations and that's why
645        they lag behind. The <code class="computeroutput"><span class="identifier">disperse</span> <span class="identifier">pointer</span> <span class="identifier">list</span></code>
646        needs to make <code class="computeroutput"><span class="identifier">NumElements</span><span class="special">*</span><span class="number">2</span></code> allocations,
647        so the result is not surprising.
648      </p>
649<p>
650        The Linux test shows that standard containers perform very well against intrusive
651        containers with big objects. Nearly the same GCC version in MinGW performs
652        worse, so maybe a good memory allocator is the reason for these excellent
653        results.
654      </p>
655</div>
656<div class="section">
657<div class="titlepage"><div><div><h3 class="title">
658<a name="intrusive.performance.performance_results_reversing"></a><a class="link" href="performance.html#intrusive.performance.performance_results_reversing" title="Reversing">Reversing</a>
659</h3></div></div></div>
660<p>
661        The next test measures the time needed to complete calls to the member function
662        <code class="computeroutput"><span class="identifier">reverse</span><span class="special">()</span></code>.
663        Values (<code class="computeroutput"><span class="identifier">test_class</span></code> and <code class="computeroutput"><span class="identifier">itest_class</span></code>) and lists are created as explained
664        in the previous section.
665      </p>
666<p>
667        Note that for pointer lists, <code class="computeroutput"><span class="identifier">reverse</span></code>
668        <span class="bold"><strong>does not need to access <code class="computeroutput"><span class="identifier">test_class</span></code>
669        values stored in another list or vector</strong></span>, since this function just
670        needs to adjust internal pointers, so in theory all tested lists need to
671        perform the same operations.
672      </p>
673<p>
674        These are the results:
675      </p>
676<div class="table">
677<a name="intrusive.performance.performance_results_reversing.reverse_times_for_visual_c_7_1_w"></a><p class="title"><b>Table 19.5. Reverse times for Visual C++ 7.1 / Windows XP</b></p>
678<div class="table-contents"><table class="table" summary="Reverse times for Visual C++ 7.1 / Windows XP">
679<colgroup>
680<col>
681<col>
682<col>
683</colgroup>
684<thead><tr>
685<th>
686                <p>
687                  Container
688                </p>
689              </th>
690<th>
691                <p>
692                  Time in us/iteration (small object / big object)
693                </p>
694              </th>
695<th>
696                <p>
697                  Normalized time (small object / big object)
698                </p>
699              </th>
700</tr></thead>
701<tbody>
702<tr>
703<td>
704                <p>
705                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
706                  list
707                </p>
708              </td>
709<td>
710                <p>
711                  2656 / 10625
712                </p>
713              </td>
714<td>
715                <p>
716                  1 / 1.83
717                </p>
718              </td>
719</tr>
720<tr>
721<td>
722                <p>
723                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
724                  list
725                </p>
726              </td>
727<td>
728                <p>
729                  2812 / 10937
730                </p>
731              </td>
732<td>
733                <p>
734                  1.05 / 1.89
735                </p>
736              </td>
737</tr>
738<tr>
739<td>
740                <p>
741                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
742                  list
743                </p>
744              </td>
745<td>
746                <p>
747                  2710 / 10781
748                </p>
749              </td>
750<td>
751                <p>
752                  1.02 / 1.86
753                </p>
754              </td>
755</tr>
756<tr>
757<td>
758                <p>
759                  Standard list
760                </p>
761              </td>
762<td>
763                <p>
764                  5781 / 14531
765                </p>
766              </td>
767<td>
768                <p>
769                  2.17 / 2.51
770                </p>
771              </td>
772</tr>
773<tr>
774<td>
775                <p>
776                  Standard compact pointer list
777                </p>
778              </td>
779<td>
780                <p>
781                  5781 / 5781
782                </p>
783              </td>
784<td>
785                <p>
786                  2.17 / 1
787                </p>
788              </td>
789</tr>
790<tr>
791<td>
792                <p>
793                  Standard disperse pointer list
794                </p>
795              </td>
796<td>
797                <p>
798                  10781 / 15781
799                </p>
800              </td>
801<td>
802                <p>
803                  4.05 / 2.72
804                </p>
805              </td>
806</tr>
807</tbody>
808</table></div>
809</div>
810<br class="table-break"><div class="table">
811<a name="intrusive.performance.performance_results_reversing.reverse_times_for_gcc_4_1_1_ming"></a><p class="title"><b>Table 19.6. Reverse times for GCC 4.1.1 / MinGW over Windows XP</b></p>
812<div class="table-contents"><table class="table" summary="Reverse times for GCC 4.1.1 / MinGW over Windows XP">
813<colgroup>
814<col>
815<col>
816<col>
817</colgroup>
818<thead><tr>
819<th>
820                <p>
821                  Container
822                </p>
823              </th>
824<th>
825                <p>
826                  Time in us/iteration (small object / big object)
827                </p>
828              </th>
829<th>
830                <p>
831                  Normalized time (small object / big object)
832                </p>
833              </th>
834</tr></thead>
835<tbody>
836<tr>
837<td>
838                <p>
839                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
840                  list
841                </p>
842              </td>
843<td>
844                <p>
845                  2656 / 10781
846                </p>
847              </td>
848<td>
849                <p>
850                  1 / 2.22
851                </p>
852              </td>
853</tr>
854<tr>
855<td>
856                <p>
857                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
858                  list
859                </p>
860              </td>
861<td>
862                <p>
863                  2656 / 10781
864                </p>
865              </td>
866<td>
867                <p>
868                  1 / 2.22
869                </p>
870              </td>
871</tr>
872<tr>
873<td>
874                <p>
875                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
876                  list
877                </p>
878              </td>
879<td>
880                <p>
881                  2812 / 10781
882                </p>
883              </td>
884<td>
885                <p>
886                  1.02 / 2.22
887                </p>
888              </td>
889</tr>
890<tr>
891<td>
892                <p>
893                  Standard list
894                </p>
895              </td>
896<td>
897                <p>
898                  4843 / 12500
899                </p>
900              </td>
901<td>
902                <p>
903                  1.82 / 2.58
904                </p>
905              </td>
906</tr>
907<tr>
908<td>
909                <p>
910                  Standard compact pointer list
911                </p>
912              </td>
913<td>
914                <p>
915                  4843 / 4843
916                </p>
917              </td>
918<td>
919                <p>
920                  1.82 / 1
921                </p>
922              </td>
923</tr>
924<tr>
925<td>
926                <p>
927                  Standard disperse pointer list
928                </p>
929              </td>
930<td>
931                <p>
932                  9218 / 12968
933                </p>
934              </td>
935<td>
936                <p>
937                  3.47 / 2.67
938                </p>
939              </td>
940</tr>
941</tbody>
942</table></div>
943</div>
944<br class="table-break"><div class="table">
945<a name="intrusive.performance.performance_results_reversing.reverse_times_for_gcc_4_1_2_linu"></a><p class="title"><b>Table 19.7. Reverse times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)</b></p>
946<div class="table-contents"><table class="table" summary="Reverse times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)">
947<colgroup>
948<col>
949<col>
950<col>
951</colgroup>
952<thead><tr>
953<th>
954                <p>
955                  Container
956                </p>
957              </th>
958<th>
959                <p>
960                  Time in us/iteration (small object / big object)
961                </p>
962              </th>
963<th>
964                <p>
965                  Normalized time (small object / big object)
966                </p>
967              </th>
968</tr></thead>
969<tbody>
970<tr>
971<td>
972                <p>
973                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
974                  list
975                </p>
976              </td>
977<td>
978                <p>
979                  2742 / 10847
980                </p>
981              </td>
982<td>
983                <p>
984                  1 / 3.41
985                </p>
986              </td>
987</tr>
988<tr>
989<td>
990                <p>
991                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
992                  list
993                </p>
994              </td>
995<td>
996                <p>
997                  2742 / 10847
998                </p>
999              </td>
1000<td>
1001                <p>
1002                  1 / 3.41
1003                </p>
1004              </td>
1005</tr>
1006<tr>
1007<td>
1008                <p>
1009                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1010                  list
1011                </p>
1012              </td>
1013<td>
1014                <p>
1015                  2742 / 11027
1016                </p>
1017              </td>
1018<td>
1019                <p>
1020                  1 / 3.47
1021                </p>
1022              </td>
1023</tr>
1024<tr>
1025<td>
1026                <p>
1027                  Standard list
1028                </p>
1029              </td>
1030<td>
1031                <p>
1032                  3184 / 10942
1033                </p>
1034              </td>
1035<td>
1036                <p>
1037                  1.16 / 3.44
1038                </p>
1039              </td>
1040</tr>
1041<tr>
1042<td>
1043                <p>
1044                  Standard compact pointer list
1045                </p>
1046              </td>
1047<td>
1048                <p>
1049                  3207 / 3176
1050                </p>
1051              </td>
1052<td>
1053                <p>
1054                  1.16 / 1
1055                </p>
1056              </td>
1057</tr>
1058<tr>
1059<td>
1060                <p>
1061                  Standard disperse pointer list
1062                </p>
1063              </td>
1064<td>
1065                <p>
1066                  5814 / 13381
1067                </p>
1068              </td>
1069<td>
1070                <p>
1071                  2.12 / 4.21
1072                </p>
1073              </td>
1074</tr>
1075</tbody>
1076</table></div>
1077</div>
1078<br class="table-break"><p>
1079        For small objects the results show that the compact storage of values in
1080        intrusive containers improve locality and reversing is faster than with standard
1081        containers, whose values might be dispersed in memory because each value
1082        is independently allocated. Note that the dispersed pointer list (a list
1083        of pointers to values allocated in another list) suffers more because nodes
1084        of the pointer list might be more dispersed, since allocations from both
1085        lists are interleaved in the code:
1086      </p>
1087<pre class="programlisting"><span class="comment">//Object list (holding `test_class`)</span>
1088<span class="identifier">stdlist</span> <span class="identifier">objects</span><span class="special">;</span>
1089
1090<span class="comment">//Pointer list (holding `test_class` pointers)</span>
1091<span class="identifier">stdptrlist</span> <span class="identifier">l</span><span class="special">;</span>
1092
1093<span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumElements</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
1094   <span class="comment">//Allocation from the object list</span>
1095   <span class="identifier">objects</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">(</span><span class="identifier">i</span><span class="special">));</span>
1096   <span class="comment">//Allocation from the pointer list</span>
1097   <span class="identifier">l</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(&amp;</span><span class="identifier">objects</span><span class="special">.</span><span class="identifier">back</span><span class="special">());</span>
1098<span class="special">}</span>
1099</pre>
1100<p>
1101        For big objects the compact pointer list wins because the reversal test doesn't
1102        need access to values stored in another container. Since all the allocations
1103        for nodes of this pointer list are likely to be close (since there is no
1104        other allocation in the process until the pointer list is created) locality
1105        is better than with intrusive containers. The dispersed pointer list, as
1106        with small values, has poor locality.
1107      </p>
1108</div>
1109<div class="section">
1110<div class="titlepage"><div><div><h3 class="title">
1111<a name="intrusive.performance.performance_results_sorting"></a><a class="link" href="performance.html#intrusive.performance.performance_results_sorting" title="Sorting">Sorting</a>
1112</h3></div></div></div>
1113<p>
1114        The next test measures the time needed to complete calls to the member function
1115        <code class="computeroutput"><span class="identifier">sort</span><span class="special">(</span><span class="identifier">Pred</span> <span class="identifier">pred</span><span class="special">)</span></code>. Values (<code class="computeroutput"><span class="identifier">test_class</span></code>
1116        and <code class="computeroutput"><span class="identifier">itest_class</span></code>) and lists
1117        are created as explained in the first section. The values will be sorted
1118        in ascending and descending order each iteration. For example, if <span class="emphasis"><em>l</em></span>
1119        is a list:
1120      </p>
1121<pre class="programlisting"><span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumIter</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
1122   <span class="keyword">if</span><span class="special">(!(</span><span class="identifier">i</span> <span class="special">%</span> <span class="number">2</span><span class="special">))</span>
1123      <span class="identifier">l</span><span class="special">.</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">greater</span><span class="special">&lt;</span><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;());</span>
1124   <span class="keyword">else</span>
1125      <span class="identifier">l</span><span class="special">.</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special">&lt;</span><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;());</span>
1126<span class="special">}</span>
1127</pre>
1128<p>
1129        For a pointer list, the function object will be adapted using <code class="computeroutput"><span class="identifier">func_ptr_adaptor</span></code>:
1130      </p>
1131<pre class="programlisting"><span class="keyword">for</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span> <span class="identifier">i</span> <span class="special">&lt;</span> <span class="identifier">NumIter</span><span class="special">;</span> <span class="special">++</span><span class="identifier">i</span><span class="special">){</span>
1132   <span class="keyword">if</span><span class="special">(!(</span><span class="identifier">i</span> <span class="special">%</span> <span class="number">2</span><span class="special">))</span>
1133      <span class="identifier">l</span><span class="special">.</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">func_ptr_adaptor</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">greater</span><span class="special">&lt;</span><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
1134   <span class="keyword">else</span>
1135      <span class="identifier">l</span><span class="special">.</span><span class="identifier">sort</span><span class="special">(</span><span class="identifier">func_ptr_adaptor</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">less</span><span class="special">&lt;</span><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">value_type</span><span class="special">&gt;</span> <span class="special">&gt;());</span>
1136<span class="special">}</span>
1137</pre>
1138<p>
1139        Note that for pointer lists, <code class="computeroutput"><span class="identifier">sort</span></code>
1140        will take a function object that <span class="bold"><strong>will access <code class="computeroutput"><span class="identifier">test_class</span></code> values stored in another list
1141        or vector</strong></span>, so pointer lists will suffer an extra indirection:
1142        they will need to access the <code class="computeroutput"><span class="identifier">test_class</span></code>
1143        values stored in another container to compare two elements.
1144      </p>
1145<p>
1146        These are the results:
1147      </p>
1148<div class="table">
1149<a name="intrusive.performance.performance_results_sorting.sort_times_for_visual_c_7_1_wind"></a><p class="title"><b>Table 19.8. Sort times for Visual C++ 7.1 / Windows XP</b></p>
1150<div class="table-contents"><table class="table" summary="Sort times for Visual C++ 7.1 / Windows XP">
1151<colgroup>
1152<col>
1153<col>
1154<col>
1155</colgroup>
1156<thead><tr>
1157<th>
1158                <p>
1159                  Container
1160                </p>
1161              </th>
1162<th>
1163                <p>
1164                  Time in us/iteration (small object / big object)
1165                </p>
1166              </th>
1167<th>
1168                <p>
1169                  Normalized time (small object / big object)
1170                </p>
1171              </th>
1172</tr></thead>
1173<tbody>
1174<tr>
1175<td>
1176                <p>
1177                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1178                  list
1179                </p>
1180              </td>
1181<td>
1182                <p>
1183                  16093 / 38906
1184                </p>
1185              </td>
1186<td>
1187                <p>
1188                  1 / 1
1189                </p>
1190              </td>
1191</tr>
1192<tr>
1193<td>
1194                <p>
1195                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1196                  list
1197                </p>
1198              </td>
1199<td>
1200                <p>
1201                  16093 / 39062
1202                </p>
1203              </td>
1204<td>
1205                <p>
1206                  1 / 1
1207                </p>
1208              </td>
1209</tr>
1210<tr>
1211<td>
1212                <p>
1213                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1214                  list
1215                </p>
1216              </td>
1217<td>
1218                <p>
1219                  16093 / 38906
1220                </p>
1221              </td>
1222<td>
1223                <p>
1224                  1 / 1
1225                </p>
1226              </td>
1227</tr>
1228<tr>
1229<td>
1230                <p>
1231                  Standard list
1232                </p>
1233              </td>
1234<td>
1235                <p>
1236                  32343 / 56406
1237                </p>
1238              </td>
1239<td>
1240                <p>
1241                  2.0 / 1.44
1242                </p>
1243              </td>
1244</tr>
1245<tr>
1246<td>
1247                <p>
1248                  Standard compact pointer list
1249                </p>
1250              </td>
1251<td>
1252                <p>
1253                  33593 / 46093
1254                </p>
1255              </td>
1256<td>
1257                <p>
1258                  2.08 / 1.18
1259                </p>
1260              </td>
1261</tr>
1262<tr>
1263<td>
1264                <p>
1265                  Standard disperse pointer list
1266                </p>
1267              </td>
1268<td>
1269                <p>
1270                  46875 / 68593
1271                </p>
1272              </td>
1273<td>
1274                <p>
1275                  2.91 / 1.76
1276                </p>
1277              </td>
1278</tr>
1279</tbody>
1280</table></div>
1281</div>
1282<br class="table-break"><div class="table">
1283<a name="intrusive.performance.performance_results_sorting.sort_times_for_gcc_4_1_1_mingw_o"></a><p class="title"><b>Table 19.9. Sort times for GCC 4.1.1 / MinGW over Windows XP</b></p>
1284<div class="table-contents"><table class="table" summary="Sort times for GCC 4.1.1 / MinGW over Windows XP">
1285<colgroup>
1286<col>
1287<col>
1288<col>
1289</colgroup>
1290<thead><tr>
1291<th>
1292                <p>
1293                  Container
1294                </p>
1295              </th>
1296<th>
1297                <p>
1298                  Time in us/iteration (small object / big object)
1299                </p>
1300              </th>
1301<th>
1302                <p>
1303                  Normalized time (small object / big object)
1304                </p>
1305              </th>
1306</tr></thead>
1307<tbody>
1308<tr>
1309<td>
1310                <p>
1311                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1312                  list
1313                </p>
1314              </td>
1315<td>
1316                <p>
1317                  15000 / 39218
1318                </p>
1319              </td>
1320<td>
1321                <p>
1322                  1 / 1
1323                </p>
1324              </td>
1325</tr>
1326<tr>
1327<td>
1328                <p>
1329                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1330                  list
1331                </p>
1332              </td>
1333<td>
1334                <p>
1335                  15156 / 39531
1336                </p>
1337              </td>
1338<td>
1339                <p>
1340                  1.01 / 1.01
1341                </p>
1342              </td>
1343</tr>
1344<tr>
1345<td>
1346                <p>
1347                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1348                  list
1349                </p>
1350              </td>
1351<td>
1352                <p>
1353                  15156 / 39531
1354                </p>
1355              </td>
1356<td>
1357                <p>
1358                  1.01 / 1.01
1359                </p>
1360              </td>
1361</tr>
1362<tr>
1363<td>
1364                <p>
1365                  Standard list
1366                </p>
1367              </td>
1368<td>
1369                <p>
1370                  34218 / 56875
1371                </p>
1372              </td>
1373<td>
1374                <p>
1375                  2.28 / 1.45
1376                </p>
1377              </td>
1378</tr>
1379<tr>
1380<td>
1381                <p>
1382                  Standard compact pointer list
1383                </p>
1384              </td>
1385<td>
1386                <p>
1387                  35468 / 49218
1388                </p>
1389              </td>
1390<td>
1391                <p>
1392                  2.36 / 1.25
1393                </p>
1394              </td>
1395</tr>
1396<tr>
1397<td>
1398                <p>
1399                  Standard disperse pointer list
1400                </p>
1401              </td>
1402<td>
1403                <p>
1404                  47656 / 70156
1405                </p>
1406              </td>
1407<td>
1408                <p>
1409                  3.17 / 1.78
1410                </p>
1411              </td>
1412</tr>
1413</tbody>
1414</table></div>
1415</div>
1416<br class="table-break"><div class="table">
1417<a name="intrusive.performance.performance_results_sorting.sort_times_for_gcc_4_1_2_linux_k"></a><p class="title"><b>Table 19.10. Sort times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)</b></p>
1418<div class="table-contents"><table class="table" summary="Sort times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)">
1419<colgroup>
1420<col>
1421<col>
1422<col>
1423</colgroup>
1424<thead><tr>
1425<th>
1426                <p>
1427                  Container
1428                </p>
1429              </th>
1430<th>
1431                <p>
1432                  Time in us/iteration (small object / big object)
1433                </p>
1434              </th>
1435<th>
1436                <p>
1437                  Normalized time (small object / big object)
1438                </p>
1439              </th>
1440</tr></thead>
1441<tbody>
1442<tr>
1443<td>
1444                <p>
1445                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1446                  list
1447                </p>
1448              </td>
1449<td>
1450                <p>
1451                  18003 / 40795
1452                </p>
1453              </td>
1454<td>
1455                <p>
1456                  1 / 1
1457                </p>
1458              </td>
1459</tr>
1460<tr>
1461<td>
1462                <p>
1463                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1464                  list
1465                </p>
1466              </td>
1467<td>
1468                <p>
1469                  18003 / 41017
1470                </p>
1471              </td>
1472<td>
1473                <p>
1474                  1 / 1
1475                </p>
1476              </td>
1477</tr>
1478<tr>
1479<td>
1480                <p>
1481                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1482                  list
1483                </p>
1484              </td>
1485<td>
1486                <p>
1487                  18230 / 40941
1488                </p>
1489              </td>
1490<td>
1491                <p>
1492                  1.01 / 1
1493                </p>
1494              </td>
1495</tr>
1496<tr>
1497<td>
1498                <p>
1499                  Standard list
1500                </p>
1501              </td>
1502<td>
1503                <p>
1504                  26273 / 49643
1505                </p>
1506              </td>
1507<td>
1508                <p>
1509                  1.45 / 1.21
1510                </p>
1511              </td>
1512</tr>
1513<tr>
1514<td>
1515                <p>
1516                  Standard compact pointer list
1517                </p>
1518              </td>
1519<td>
1520                <p>
1521                  28540 / 43172
1522                </p>
1523              </td>
1524<td>
1525                <p>
1526                  1.58 / 1.05
1527                </p>
1528              </td>
1529</tr>
1530<tr>
1531<td>
1532                <p>
1533                  Standard disperse pointer list
1534                </p>
1535              </td>
1536<td>
1537                <p>
1538                  35077 / 57638
1539                </p>
1540              </td>
1541<td>
1542                <p>
1543                  1.94 / 1.41
1544                </p>
1545              </td>
1546</tr>
1547</tbody>
1548</table></div>
1549</div>
1550<br class="table-break"><p>
1551        The results show that intrusive containers are faster than standard containers.
1552        We can see that the pointer list holding pointers to values stored in a vector
1553        is quite fast, so the extra indirection that is needed to access the value
1554        is minimized because all the values are tightly stored, improving caching.
1555        The disperse list, on the other hand, is slower because the indirection to
1556        access values stored in the object list is more expensive than accessing
1557        values stored in a vector.
1558      </p>
1559</div>
1560<div class="section">
1561<div class="titlepage"><div><div><h3 class="title">
1562<a name="intrusive.performance.performance_results_write_access"></a><a class="link" href="performance.html#intrusive.performance.performance_results_write_access" title="Write access">Write
1563      access</a>
1564</h3></div></div></div>
1565<p>
1566        The next test measures the time needed to iterate through all the elements
1567        of a list, and increment the value of the internal <code class="computeroutput"><span class="identifier">i_</span></code>
1568        member:
1569      </p>
1570<pre class="programlisting"><span class="identifier">stdlist</span><span class="special">::</span><span class="identifier">iterator</span> <span class="identifier">it</span><span class="special">(</span><span class="identifier">l</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">l</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
1571<span class="keyword">for</span><span class="special">(;</span> <span class="identifier">it</span> <span class="special">!=</span> <span class="identifier">end</span><span class="special">;</span> <span class="special">++</span><span class="identifier">it</span><span class="special">)</span>
1572   <span class="special">++(</span><span class="identifier">it</span><span class="special">-&gt;</span><span class="identifier">i_</span><span class="special">);</span>
1573</pre>
1574<p>
1575        Values (<code class="computeroutput"><span class="identifier">test_class</span></code> and <code class="computeroutput"><span class="identifier">itest_class</span></code>) and lists are created as explained
1576        in the first section. Note that for pointer lists, the iteration will suffer
1577        an extra indirection: they will need to access the <code class="computeroutput"><span class="identifier">test_class</span></code>
1578        values stored in another container:
1579      </p>
1580<pre class="programlisting"><span class="identifier">stdptrlist</span><span class="special">::</span><span class="identifier">iterator</span> <span class="identifier">it</span><span class="special">(</span><span class="identifier">l</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">l</span><span class="special">.</span><span class="identifier">end</span><span class="special">());</span>
1581<span class="keyword">for</span><span class="special">(;</span> <span class="identifier">it</span> <span class="special">!=</span> <span class="identifier">end</span><span class="special">;</span> <span class="special">++</span><span class="identifier">it</span><span class="special">)</span>
1582   <span class="special">++((*</span><span class="identifier">it</span><span class="special">)-&gt;</span><span class="identifier">i_</span><span class="special">);</span>
1583</pre>
1584<p>
1585        These are the results:
1586      </p>
1587<div class="table">
1588<a name="intrusive.performance.performance_results_write_access.write_access_times_for_visual_c_"></a><p class="title"><b>Table 19.11. Write access times for Visual C++ 7.1 / Windows XP</b></p>
1589<div class="table-contents"><table class="table" summary="Write access times for Visual C++ 7.1 / Windows XP">
1590<colgroup>
1591<col>
1592<col>
1593<col>
1594</colgroup>
1595<thead><tr>
1596<th>
1597                <p>
1598                  Container
1599                </p>
1600              </th>
1601<th>
1602                <p>
1603                  Time in us/iteration (small object / big object)
1604                </p>
1605              </th>
1606<th>
1607                <p>
1608                  Normalized time (small object / big object)
1609                </p>
1610              </th>
1611</tr></thead>
1612<tbody>
1613<tr>
1614<td>
1615                <p>
1616                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1617                  list
1618                </p>
1619              </td>
1620<td>
1621                <p>
1622                  2031 / 8125
1623                </p>
1624              </td>
1625<td>
1626                <p>
1627                  1 / 1
1628                </p>
1629              </td>
1630</tr>
1631<tr>
1632<td>
1633                <p>
1634                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1635                  list
1636                </p>
1637              </td>
1638<td>
1639                <p>
1640                  2031 / 8281
1641                </p>
1642              </td>
1643<td>
1644                <p>
1645                  1 / 1.01
1646                </p>
1647              </td>
1648</tr>
1649<tr>
1650<td>
1651                <p>
1652                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1653                  list
1654                </p>
1655              </td>
1656<td>
1657                <p>
1658                  2031 / 8281
1659                </p>
1660              </td>
1661<td>
1662                <p>
1663                  1 / 1.01
1664                </p>
1665              </td>
1666</tr>
1667<tr>
1668<td>
1669                <p>
1670                  Standard list
1671                </p>
1672              </td>
1673<td>
1674                <p>
1675                  4218 / 10000
1676                </p>
1677              </td>
1678<td>
1679                <p>
1680                  2.07 / 1.23
1681                </p>
1682              </td>
1683</tr>
1684<tr>
1685<td>
1686                <p>
1687                  Standard compact pointer list
1688                </p>
1689              </td>
1690<td>
1691                <p>
1692                  4062 / 8437
1693                </p>
1694              </td>
1695<td>
1696                <p>
1697                  2.0 / 1.03
1698                </p>
1699              </td>
1700</tr>
1701<tr>
1702<td>
1703                <p>
1704                  Standard disperse pointer list
1705                </p>
1706              </td>
1707<td>
1708                <p>
1709                  8593 / 13125
1710                </p>
1711              </td>
1712<td>
1713                <p>
1714                  4.23 / 1.61
1715                </p>
1716              </td>
1717</tr>
1718</tbody>
1719</table></div>
1720</div>
1721<br class="table-break"><div class="table">
1722<a name="intrusive.performance.performance_results_write_access.write_access_times_for_gcc_4_1_1"></a><p class="title"><b>Table 19.12. Write access times for GCC 4.1.1 / MinGW over Windows XP</b></p>
1723<div class="table-contents"><table class="table" summary="Write access times for GCC 4.1.1 / MinGW over Windows XP">
1724<colgroup>
1725<col>
1726<col>
1727<col>
1728</colgroup>
1729<thead><tr>
1730<th>
1731                <p>
1732                  Container
1733                </p>
1734              </th>
1735<th>
1736                <p>
1737                  Time in us/iteration (small object / big object)
1738                </p>
1739              </th>
1740<th>
1741                <p>
1742                  Normalized time (small object / big object)
1743                </p>
1744              </th>
1745</tr></thead>
1746<tbody>
1747<tr>
1748<td>
1749                <p>
1750                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1751                  list
1752                </p>
1753              </td>
1754<td>
1755                <p>
1756                  2343 / 8281
1757                </p>
1758              </td>
1759<td>
1760                <p>
1761                  1 / 1
1762                </p>
1763              </td>
1764</tr>
1765<tr>
1766<td>
1767                <p>
1768                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1769                  list
1770                </p>
1771              </td>
1772<td>
1773                <p>
1774                  2500 / 8281
1775                </p>
1776              </td>
1777<td>
1778                <p>
1779                  1.06 / 1
1780                </p>
1781              </td>
1782</tr>
1783<tr>
1784<td>
1785                <p>
1786                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1787                  list
1788                </p>
1789              </td>
1790<td>
1791                <p>
1792                  2500 / 8281
1793                </p>
1794              </td>
1795<td>
1796                <p>
1797                  1.06 / 1
1798                </p>
1799              </td>
1800</tr>
1801<tr>
1802<td>
1803                <p>
1804                  Standard list
1805                </p>
1806              </td>
1807<td>
1808                <p>
1809                  4218 / 10781
1810                </p>
1811              </td>
1812<td>
1813                <p>
1814                  1.8 / 1.3
1815                </p>
1816              </td>
1817</tr>
1818<tr>
1819<td>
1820                <p>
1821                  Standard compact pointer list
1822                </p>
1823              </td>
1824<td>
1825                <p>
1826                  3906 / 8281
1827                </p>
1828              </td>
1829<td>
1830                <p>
1831                  1.66 / 1
1832                </p>
1833              </td>
1834</tr>
1835<tr>
1836<td>
1837                <p>
1838                  Standard disperse pointer list
1839                </p>
1840              </td>
1841<td>
1842                <p>
1843                  8281 / 13750
1844                </p>
1845              </td>
1846<td>
1847                <p>
1848                  3.53 / 1.66
1849                </p>
1850              </td>
1851</tr>
1852</tbody>
1853</table></div>
1854</div>
1855<br class="table-break"><div class="table">
1856<a name="intrusive.performance.performance_results_write_access.write_access_times_for_gcc_4_1_2"></a><p class="title"><b>Table 19.13. Write access times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)</b></p>
1857<div class="table-contents"><table class="table" summary="Write access times for GCC 4.1.2 / Linux Kernel 2.6.18 (OpenSuse 10.2)">
1858<colgroup>
1859<col>
1860<col>
1861<col>
1862</colgroup>
1863<thead><tr>
1864<th>
1865                <p>
1866                  Container
1867                </p>
1868              </th>
1869<th>
1870                <p>
1871                  Time in us/iteration (small object / big object)
1872                </p>
1873              </th>
1874<th>
1875                <p>
1876                  Normalized time (small object / big object)
1877                </p>
1878              </th>
1879</tr></thead>
1880<tbody>
1881<tr>
1882<td>
1883                <p>
1884                  <code class="computeroutput"><span class="identifier">normal_link</span></code> intrusive
1885                  list
1886                </p>
1887              </td>
1888<td>
1889                <p>
1890                  2286 / 8468
1891                </p>
1892              </td>
1893<td>
1894                <p>
1895                  1 / 1.1
1896                </p>
1897              </td>
1898</tr>
1899<tr>
1900<td>
1901                <p>
1902                  <code class="computeroutput"><span class="identifier">safe_link</span></code> intrusive
1903                  list
1904                </p>
1905              </td>
1906<td>
1907                <p>
1908                  2381 / 8412
1909                </p>
1910              </td>
1911<td>
1912                <p>
1913                  1.04 / 1.09
1914                </p>
1915              </td>
1916</tr>
1917<tr>
1918<td>
1919                <p>
1920                  <code class="computeroutput"><span class="identifier">auto_unlink</span></code> intrusive
1921                  list
1922                </p>
1923              </td>
1924<td>
1925                <p>
1926                  2301 / 8437
1927                </p>
1928              </td>
1929<td>
1930                <p>
1931                  1.01 / 1.1
1932                </p>
1933              </td>
1934</tr>
1935<tr>
1936<td>
1937                <p>
1938                  Standard list
1939                </p>
1940              </td>
1941<td>
1942                <p>
1943                  3044 / 9061
1944                </p>
1945              </td>
1946<td>
1947                <p>
1948                  1.33 / 1.18
1949                </p>
1950              </td>
1951</tr>
1952<tr>
1953<td>
1954                <p>
1955                  Standard compact pointer list
1956                </p>
1957              </td>
1958<td>
1959                <p>
1960                  2755 / 7660
1961                </p>
1962              </td>
1963<td>
1964                <p>
1965                  1.20 / 1
1966                </p>
1967              </td>
1968</tr>
1969<tr>
1970<td>
1971                <p>
1972                  Standard disperse pointer list
1973                </p>
1974              </td>
1975<td>
1976                <p>
1977                  6118 / 12453
1978                </p>
1979              </td>
1980<td>
1981                <p>
1982                  2.67 / 1.62
1983                </p>
1984              </td>
1985</tr>
1986</tbody>
1987</table></div>
1988</div>
1989<br class="table-break"><p>
1990        As with the read access test, the results show that intrusive containers
1991        outperform all other containers if the values are tightly packed in a vector.
1992        The disperse list is again the slowest.
1993      </p>
1994</div>
1995<div class="section">
1996<div class="titlepage"><div><div><h3 class="title">
1997<a name="intrusive.performance.performance_results_conclusions"></a><a class="link" href="performance.html#intrusive.performance.performance_results_conclusions" title="Conclusions">Conclusions</a>
1998</h3></div></div></div>
1999<p>
2000        Intrusive containers can offer performance benefits that cannot be achieved
2001        with equivalent non-intrusive containers. Memory locality improvements are
2002        noticeable when the objects to be inserted are small. Minimizing memory allocation/deallocation
2003        calls is also an important factor and intrusive containers make this simple
2004        if all objects to be inserted in intrusive containers are allocated using
2005        <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span></code> or <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">deque</span></code>.
2006      </p>
2007</div>
2008</div>
2009<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
2010<td align="left"></td>
2011<td align="right"><div class="copyright-footer">Copyright © 2005 Olaf Krzikalla<br>Copyright © 2006-2015 Ion Gaztanaga<p>
2012        Distributed under the Boost Software License, Version 1.0. (See accompanying
2013        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
2014      </p>
2015</div></td>
2016</tr></table>
2017<hr>
2018<div class="spirit-nav">
2019<a accesskey="p" href="design_notes.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../intrusive.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="release_notes.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
2020</div>
2021</body>
2022</html>
2023