• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<html>
2<head>
3<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4<title>Performance considerations</title>
5<link rel="stylesheet" href="../../../../../../doc/src/boostbook.css" type="text/css">
6<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7<link rel="home" href="../../index.html" title="Boost.Optional">
8<link rel="up" href="../../optional/tutorial.html" title="Tutorial">
9<link rel="prev" href="type_requirements.html" title="Type requirements">
10<link rel="next" href="../../optional/reference.html" title="Reference">
11</head>
12<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13<table cellpadding="2" width="100%"><tr>
14<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15<td align="center"><a href="../../../../../../index.html">Home</a></td>
16<td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19<td align="center"><a href="../../../../../../more/index.htm">More</a></td>
20</tr></table>
21<hr>
22<div class="spirit-nav">
23<a accesskey="p" href="type_requirements.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../../optional/tutorial.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="../../optional/reference.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
24</div>
25<div class="section">
26<div class="titlepage"><div><div><h3 class="title">
27<a name="boost_optional.tutorial.performance_considerations"></a><a class="link" href="performance_considerations.html" title="Performance considerations">Performance
28      considerations</a>
29</h3></div></div></div>
30<p>
31        Technical details aside, the memory layout of <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>
32        for a generic <code class="computeroutput"><span class="identifier">T</span></code> is more-less
33        this:
34      </p>
35<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
36<span class="keyword">class</span> <span class="identifier">optional</span>
37<span class="special">{</span>
38  <span class="keyword">bool</span> <span class="identifier">_initialized</span><span class="special">;</span>
39  <span class="identifier">std</span><span class="special">::</span><span class="identifier">aligned_storage_t</span><span class="special">&lt;</span><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">t</span><span class="special">),</span> <span class="keyword">alignof</span><span class="special">(</span><span class="identifier">T</span><span class="special">)&gt;</span> <span class="identifier">_storage</span><span class="special">;</span>
40<span class="special">};</span>
41</pre>
42<p>
43        Lifetime of the <code class="computeroutput"><span class="identifier">T</span></code> inside
44        <code class="computeroutput"><span class="identifier">_storage</span></code> is manually controlled
45        with placement-<code class="computeroutput"><span class="keyword">new</span></code>s and pseudo-destructor
46        calls. However, for scalar <code class="computeroutput"><span class="identifier">T</span></code>s
47        we use a different way of storage, by simply holding a <code class="computeroutput"><span class="identifier">T</span></code>:
48      </p>
49<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
50<span class="keyword">class</span> <span class="identifier">optional</span>
51<span class="special">{</span>
52  <span class="keyword">bool</span> <span class="identifier">_initialized</span><span class="special">;</span>
53  <span class="identifier">T</span> <span class="identifier">_storage</span><span class="special">;</span>
54<span class="special">};</span>
55</pre>
56<p>
57        We call it a <span class="emphasis"><em>direct</em></span> storage. This makes <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code> a
58        trivially-copyable type for scalar <code class="computeroutput"><span class="identifier">T</span></code>s.
59        This only works for compilers that support defaulted functions (including
60        defaulted move assignment and constructor). On compilers without defaulted
61        functions we still use the direct storage, but <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span></code>
62        is no longer recognized as trivially-copyable. Apart from scalar types, we
63        leave the programmer a way of customizing her type, so that it is reconized
64        by <code class="computeroutput"><span class="identifier">optional</span></code> as candidate
65        for optimized storage, by specializing type trait <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">opitonal_config</span><span class="special">::</span><span class="identifier">optional_uses_direct_storage_for</span></code>:
66      </p>
67<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">X</span> <span class="comment">// not trivial</span>
68<span class="special">{</span>
69  <span class="identifier">X</span><span class="special">()</span> <span class="special">{}</span>
70<span class="special">};</span>
71
72<span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">optional_config</span> <span class="special">{</span>
73
74  <span class="keyword">template</span> <span class="special">&lt;&gt;</span> <span class="keyword">struct</span> <span class="identifier">optional_uses_direct_storage_for</span><span class="special">&lt;</span><span class="identifier">X</span><span class="special">&gt;</span> <span class="special">:</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">true_type</span> <span class="special">{};</span>
75
76<span class="special">}}</span>
77</pre>
78<h5>
79<a name="boost_optional.tutorial.performance_considerations.h0"></a>
80        <span class="phrase"><a name="boost_optional.tutorial.performance_considerations.controlling_the_size"></a></span><a class="link" href="performance_considerations.html#boost_optional.tutorial.performance_considerations.controlling_the_size">Controlling
81        the size</a>
82      </h5>
83<p>
84        For the purpose of the following analysis, considering memory layouts, we
85        can think of it as:
86      </p>
87<pre class="programlisting"><span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
88<span class="keyword">class</span> <span class="identifier">optional</span>
89<span class="special">{</span>
90  <span class="keyword">bool</span> <span class="identifier">_initialized</span><span class="special">;</span>
91  <span class="identifier">T</span> <span class="identifier">_storage</span><span class="special">;</span>
92<span class="special">};</span>
93</pre>
94<p>
95        Given type <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span></code>, and
96        assuming that <code class="computeroutput"><span class="keyword">sizeof</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="special">==</span>
97        <span class="number">4</span></code>, we will get <code class="computeroutput"><span class="keyword">sizeof</span><span class="special">(</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;)</span>
98        <span class="special">==</span> <span class="number">8</span></code>.
99        This is so because of the alignment rules, for our two members we get the
100        following alignment:
101      </p>
102<p>
103        <span class="inlinemediaobject"><img src="../../images/opt_align1.png" alt="opt_align1"></span>
104      </p>
105<p>
106        This means you can fit twice as many <code class="computeroutput"><span class="keyword">int</span></code>s
107        as <code class="computeroutput"><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span></code>s into
108        the same space of memory. Therefore, if the size of the objects is critical
109        for your application (e.g., because you want to utilize your CPU cache in
110        order to gain performance) and you have determined you are willing to trade
111        the code clarity, it is recommended that you simply go with type <code class="computeroutput"><span class="keyword">int</span></code> and use some 'magic value' to represent
112        <span class="emphasis"><em>not-an-int</em></span>, or use something like <a href="https://github.com/akrzemi1/markable" target="_top"><code class="computeroutput"><span class="identifier">markable</span></code></a> library.
113      </p>
114<p>
115        Even if you cannot spare any value of <code class="computeroutput"><span class="keyword">int</span></code>
116        to represent <span class="emphasis"><em>not-an-int</em></span> (e.g., because every value is
117        useful, or you do want to signal <span class="emphasis"><em>not-an-int</em></span> explicitly),
118        at least for <code class="computeroutput"><span class="identifier">Trivial</span></code> types
119        you should consider storing the value and the <code class="computeroutput"><span class="keyword">bool</span></code>
120        flag representing the <span class="emphasis"><em>null-state</em></span> separately. Consider
121        the following class:
122      </p>
123<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Record</span>
124<span class="special">{</span>
125  <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">_min</span><span class="special">;</span>
126  <span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="identifier">_max</span><span class="special">;</span>
127<span class="special">};</span>
128</pre>
129<p>
130        Its memory layout can be depicted as follows:
131      </p>
132<p>
133        <span class="inlinemediaobject"><img src="../../images/opt_align2.png" alt="opt_align2"></span>
134      </p>
135<p>
136        This is exactly the same as if we had the following members:
137      </p>
138<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Record</span>
139<span class="special">{</span>
140  <span class="keyword">bool</span> <span class="identifier">_has_min</span><span class="special">;</span>
141  <span class="keyword">int</span>  <span class="identifier">_min</span><span class="special">;</span>
142  <span class="keyword">bool</span> <span class="identifier">_has_max</span><span class="special">;</span>
143  <span class="keyword">int</span>  <span class="identifier">_max</span><span class="special">;</span>
144<span class="special">};</span>
145</pre>
146<p>
147        But when they are stored separately, we at least have an option to reorder
148        them like this:
149      </p>
150<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Record</span>
151<span class="special">{</span>
152  <span class="keyword">bool</span> <span class="identifier">_has_min</span><span class="special">;</span>
153  <span class="keyword">bool</span> <span class="identifier">_has_max</span><span class="special">;</span>
154  <span class="keyword">int</span>  <span class="identifier">_min</span><span class="special">;</span>
155  <span class="keyword">int</span>  <span class="identifier">_max</span><span class="special">;</span>
156<span class="special">};</span>
157</pre>
158<p>
159        Which gives us the following layout (and smaller total size):
160      </p>
161<p>
162        <span class="inlinemediaobject"><img src="../../images/opt_align3.png" alt="opt_align3"></span>
163      </p>
164<p>
165        Sometimes it requires detailed consideration what data we make optional.
166        In our case above, if we determine that both minimum and maximum value can
167        be provided or not provided together, but one is never provided without the
168        other, we can make only one optional memebr:
169      </p>
170<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Limits</span>
171<span class="special">{</span>
172  <span class="keyword">int</span>  <span class="identifier">_min</span><span class="special">;</span>
173  <span class="keyword">int</span>  <span class="identifier">_max</span><span class="special">;</span>
174<span class="special">};</span>
175
176<span class="keyword">struct</span> <span class="identifier">Record</span>
177<span class="special">{</span>
178  <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Limits</span><span class="special">&gt;</span> <span class="identifier">_limits</span><span class="special">;</span>
179<span class="special">};</span>
180</pre>
181<p>
182        This would give us the following layout:
183      </p>
184<p>
185        <span class="inlinemediaobject"><img src="../../images/opt_align4.png" alt="opt_align4"></span>
186      </p>
187<h5>
188<a name="boost_optional.tutorial.performance_considerations.h1"></a>
189        <span class="phrase"><a name="boost_optional.tutorial.performance_considerations.optional_function_parameters"></a></span><a class="link" href="performance_considerations.html#boost_optional.tutorial.performance_considerations.optional_function_parameters">Optional
190        function parameters</a>
191      </h5>
192<p>
193        Having function parameters of type <code class="computeroutput"><span class="keyword">const</span>
194        <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;&amp;</span></code>
195        may incur certain unexpected run-time cost connected to copy construction
196        of <code class="computeroutput"><span class="identifier">T</span></code>. Consider the following
197        code.
198      </p>
199<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">fun</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Big</span><span class="special">&gt;&amp;</span> <span class="identifier">v</span><span class="special">)</span>
200<span class="special">{</span>
201  <span class="keyword">if</span> <span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="identifier">doSomethingWith</span><span class="special">(*</span><span class="identifier">v</span><span class="special">);</span>
202  <span class="keyword">else</span>   <span class="identifier">doSomethingElse</span><span class="special">();</span>
203<span class="special">}</span>
204
205<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
206<span class="special">{</span>
207  <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Big</span><span class="special">&gt;</span> <span class="identifier">ov</span><span class="special">;</span>
208  <span class="identifier">Big</span> <span class="identifier">v</span><span class="special">;</span>
209  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">none</span><span class="special">);</span>
210  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">ov</span><span class="special">);</span> <span class="comment">// no copy</span>
211  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>  <span class="comment">// copy constructor of Big</span>
212<span class="special">}</span>
213</pre>
214<p>
215        No copy elision or move semantics can save us from copying type <code class="computeroutput"><span class="identifier">Big</span></code> here. Not that we need any copy, but
216        this is how <code class="computeroutput"><span class="identifier">optional</span></code> works.
217        In order to avoid copying in this case, one could provide second overload
218        of <code class="computeroutput"><span class="identifier">fun</span></code>:
219      </p>
220<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">fun</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">Big</span><span class="special">&amp;</span> <span class="identifier">v</span><span class="special">)</span>
221<span class="special">{</span>
222  <span class="identifier">doSomethingWith</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>
223<span class="special">}</span>
224
225<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
226<span class="special">{</span>
227  <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Big</span><span class="special">&gt;</span> <span class="identifier">ov</span><span class="special">;</span>
228  <span class="identifier">Big</span> <span class="identifier">v</span><span class="special">;</span>
229  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">ov</span><span class="special">);</span> <span class="comment">// no copy</span>
230  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>  <span class="comment">// no copy: second overload selected</span>
231<span class="special">}</span>
232</pre>
233<p>
234        Alternatively, you could consider using an optional reference instead:
235      </p>
236<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">fun</span><span class="special">(</span><span class="identifier">optional</span><span class="special">&lt;</span><span class="keyword">const</span> <span class="identifier">Big</span><span class="special">&amp;&gt;</span> <span class="identifier">v</span><span class="special">)</span> <span class="comment">// note where the reference is</span>
237<span class="special">{</span>
238  <span class="keyword">if</span> <span class="special">(</span><span class="identifier">v</span><span class="special">)</span> <span class="identifier">doSomethingWith</span><span class="special">(*</span><span class="identifier">v</span><span class="special">);</span>
239  <span class="keyword">else</span>   <span class="identifier">doSomethingElse</span><span class="special">();</span>
240<span class="special">}</span>
241
242<span class="keyword">int</span> <span class="identifier">main</span><span class="special">()</span>
243<span class="special">{</span>
244  <span class="identifier">optional</span><span class="special">&lt;</span><span class="identifier">Big</span><span class="special">&gt;</span> <span class="identifier">ov</span><span class="special">;</span>
245  <span class="identifier">Big</span> <span class="identifier">v</span><span class="special">;</span>
246  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">none</span><span class="special">);</span>
247  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">ov</span><span class="special">);</span> <span class="comment">// doesn't compile</span>
248  <span class="identifier">fun</span><span class="special">(</span><span class="identifier">v</span><span class="special">);</span>  <span class="comment">// no copy</span>
249<span class="special">}</span>
250</pre>
251</div>
252<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
253<td align="left"></td>
254<td align="right"><div class="copyright-footer">Copyright © 2003-2007 Fernando Luis Cacciola Carballal<br>Copyright © 2014-2018 Andrzej Krzemieński<p>
255        Distributed under the Boost Software License, Version 1.0. (See accompanying
256        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>)
257      </p>
258</div></td>
259</tr></table>
260<hr>
261<div class="spirit-nav">
262<a accesskey="p" href="type_requirements.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../../optional/tutorial.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="../../optional/reference.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
263</div>
264</body>
265</html>
266