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"><</span><span class="identifier">T</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</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">)></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">></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"><></span> <span class="keyword">struct</span> <span class="identifier">optional_uses_direct_storage_for</span><span class="special"><</span><span class="identifier">X</span><span class="special">></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"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">>)</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"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="keyword">int</span><span class="special">></span> <span class="identifier">_min</span><span class="special">;</span> 126 <span class="identifier">optional</span><span class="special"><</span><span class="keyword">int</span><span class="special">></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"><</span><span class="identifier">Limits</span><span class="special">></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"><</span><span class="identifier">T</span><span class="special">>&</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"><</span><span class="identifier">Big</span><span class="special">>&</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"><</span><span class="identifier">Big</span><span class="special">></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">&</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"><</span><span class="identifier">Big</span><span class="special">></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"><</span><span class="keyword">const</span> <span class="identifier">Big</span><span class="special">&></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"><</span><span class="identifier">Big</span><span class="special">></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