<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>memory efficiency &#8211; Wade Tregaskis</title>
	<atom:link href="https://wadetregaskis.com/tags/memory-efficiency/feed/" rel="self" type="application/rss+xml" />
	<link>https://wadetregaskis.com</link>
	<description></description>
	<lastBuildDate>Wed, 28 Feb 2024 05:18:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wadetregaskis.com/wp-content/uploads/2016/03/Stitch-512x512-1-256x256.png</url>
	<title>memory efficiency &#8211; Wade Tregaskis</title>
	<link>https://wadetregaskis.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">226351702</site>	<item>
		<title>A brief introduction to type memory layout in Swift</title>
		<link>https://wadetregaskis.com/a-brief-introduction-to-type-memory-layout-in-swift/</link>
					<comments>https://wadetregaskis.com/a-brief-introduction-to-type-memory-layout-in-swift/#comments</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Wed, 28 Feb 2024 05:18:44 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[alignment]]></category>
		<category><![CDATA[memory efficiency]]></category>
		<category><![CDATA[memory layout]]></category>
		<category><![CDATA[padding]]></category>
		<category><![CDATA[Swift]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=7803</guid>

					<description><![CDATA[Most of the time we Swift programmers don&#8217;t really think about how our types &#8211; structs, classes, actors, enums, etc &#8211; are represented in memory. We just deal with them abstractly, knowing that somehow the compiler boils them down to a bunch of bytes, handling all the complexity of wrangling those bytes for us. However,&#8230; <a class="read-more-link" href="https://wadetregaskis.com/a-brief-introduction-to-type-memory-layout-in-swift/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Most of the time we Swift programmers don&#8217;t really think about how our types &#8211; structs, classes, actors, enums, etc &#8211; are represented in memory.  We just deal with them abstractly, knowing that somehow the compiler boils them down to a bunch of bytes, handling all the complexity of wrangling those bytes for us.</p>



<p>However, whether we realise it or not, we humans do actually determine how our types are laid out in memory, and how much memory they use &#8211; and in more subtle ways than you might realise.  We can have a significant impact on how <em>efficient</em> our memory usage is &#8211; and consequently runtime performance &#8211; based on things as innocuous as in what order we declare stored properties.</p>



<p>I&#8217;m going to start at the beginning, but if you find the foundations &amp; theory uninteresting, at least read the subsequent section headings for the key takeaways.</p>



<h1 class="wp-block-heading">Determining how Swift lays out a type</h1>



<p>The Swift standard library includes a handy utility, <code><a href="https://developer.apple.com/documentation/swift/memorylayout" data-wpel-link="external" target="_blank" rel="external noopener">MemoryLayout</a></code>.  It reports three attributes regarding how a target type is actually laid out in memory by the compiler:</p>



<ul class="wp-block-list">
<li>&#8220;<strong>Size</strong>&#8221; &#8211; the number of <em>contiguous</em> bytes required to store an instance of the type.  This is not necessarily the <em>optimal</em> size (as we&#8217;ll see later) nor the <em>actual</em> size, so it&#8217;s not terribly useful other than as a way to infer other, more interesting attributes.</li>



<li><strong>Stride</strong> &#8211; the <em>actual</em> number of bytes required to store an instance of the type<sup data-fn="13cd788d-5855-4a1e-a1bd-5d8bf2c204ed" class="fn"><a href="#13cd788d-5855-4a1e-a1bd-5d8bf2c204ed" id="13cd788d-5855-4a1e-a1bd-5d8bf2c204ed-link">1</a></sup>, taking into account its alignment requirements.</li>



<li><strong>Alignment</strong> &#8211; the address of any instance of the type must be evenly divisible by this power of two.<br><br>Alignment is a tricky concept and pivotal to how &amp; why data types are laid out the way they are (not just in Swift, but in practically all programming languages).  Thankfully, you don&#8217;t really need to understand alignment for the purposes of this post &#8211; just consider it a &#8220;magic&#8221; number dictated by hardware and compilers for performance and portability.  Or see e.g. <a href="https://en.wikipedia.org/wiki/Data_structure_alignment" data-wpel-link="external" target="_blank" rel="external noopener">Wikipedia</a> if you really want to dig into it.</li>
</ul>



<p>Using <code><a href="https://developer.apple.com/documentation/swift/mirror" data-wpel-link="external" target="_blank" rel="external noopener">Mirror</a></code>, it&#8217;s also possible to sum up the size of the stored properties for structs, classes, etc.  That tells you the <em>nominal</em> size, if alignment weren&#8217;t an issue.</p>



<p>The difference between the <em>nominal</em> <em>size</em> and <em>stride</em> (if any) is the <em>padding</em>.  Padding bytes aren&#8217;t actually used to store anything.  They are wasted space.  Minimising padding is generally good, especially if doing so doesn&#8217;t require breaking any alignment requirements.  Padding can be internal (between stored properties within the type) or trailing (after all stored properties within the type) &#8211; we&#8217;ll dig into the practical difference later.</p>



<p>So, armed will this knowledge and tools, let&#8217;s interrogate some types.</p>



<h1 class="wp-block-heading">Scalars tend to be pleasantly boring</h1>



<p>In general, scalars &#8211; individual numbers &amp; booleans &#8211; tend to have no padding and be aligned to their full size (known as <em>natural</em> alignment).  e.g.:</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-right" data-align="right">Type</th><th class="has-text-align-center" data-align="center">Nominal Size</th><th class="has-text-align-center" data-align="center">Contiguous Size</th><th class="has-text-align-center" data-align="center">Alignment</th><th class="has-text-align-center" data-align="center">Actual Size (Stride)</th><th class="has-text-align-center" data-align="center">Internal Padding</th><th class="has-text-align-center" data-align="center">Trailing Padding</th></tr></thead><tbody><tr><td class="has-text-align-right" data-align="right">Bool</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Int8 / UInt8</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Int16 / UInt16</td><td class="has-text-align-center" data-align="center">2</td><td class="has-text-align-center" data-align="center">2</td><td class="has-text-align-center" data-align="center">2</td><td class="has-text-align-center" data-align="center">2</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Int32 / UInt32</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Int64 / UInt64</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Float</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Double</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr></tbody></table></figure>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️  <code>Int</code> &amp; <code>UInt</code> vary in size across CPU ISAs, following the natural word size.  So, on 64-bit ISAs they are equivalent to <code>Int64</code> / <code>UInt64</code>, while on 32-bit ISAs they are equivalent to <code>Int32</code> / <code>UInt32</code>.</p>
</div></div>



<h1 class="wp-block-heading">Characters are expensive</h1>



<p><code><a href="https://developer.apple.com/documentation/swift/string" data-wpel-link="external" target="_blank" rel="external noopener">String</a></code> is a surprisingly and extremely complicated type, which is largely a topic for another time.  However, one important thing to note is its relationship to <code><a href="https://developer.apple.com/documentation/swift/character" data-wpel-link="external" target="_blank" rel="external noopener">Character</a></code>:</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-right" data-align="right">Type</th><th class="has-text-align-center" data-align="center">Nominal Size</th><th class="has-text-align-center" data-align="center">Contiguous Size</th><th class="has-text-align-center" data-align="center">Alignment</th><th class="has-text-align-center" data-align="center">Actual Size (Stride)</th><th class="has-text-align-center" data-align="center">Internal Padding</th><th class="has-text-align-center" data-align="center">Trailing Padding</th></tr></thead><tbody><tr><td class="has-text-align-right" data-align="right">Character</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">String</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr></tbody></table></figure>



<p>They&#8217;re the same!  <code>Character</code> is a lie &#8211; <a href="https://github.com/apple/swift/blob/bd46860dfbaa1471c6210595f4291873a49676f3/stdlib/public/core/Character.swift#L67" data-wpel-link="external" target="_blank" rel="external noopener">it&#8217;s actually a <code>String</code></a>!</p>



<p>There is of course more to <code>Character</code> &#8211; although it <em>is</em> a string under the covers, its API enforces that it can only ever contain a <em>single</em> character.  But that&#8217;s about it.</p>



<p>The reason is that a single character has no upper bound on its byte size &#8211; these are Unicode characters (formally known as <em><a href="https://www.unicode.org/reports/tr29/" data-wpel-link="external" target="_blank" rel="external noopener">extended grapheme clusters</a></em>), not ASCII characters that fit trivially into a single byte.  Unicode characters can be composed of <em>multiple</em> Unicode scalars (a naive notion of a Unicode &#8216;character&#8217;, that is Unicode&#8217;s basic building block) &#8211; and that&#8217;s just scratching the surface.  <a href="https://andybargh.com/about/" data-wpel-link="external" target="_blank" rel="external noopener">Andy Bargh</a> has written <a href="https://andybargh.com/unicode/" data-wpel-link="external" target="_blank" rel="external noopener">a nice Swift-centric introduction to the fun of Unicode</a>, if you want to pull on that thread.</p>



<p>So, rather than reimplementing a <em>tremendous</em> amount of complex functionality, <code>Character</code> just uses <code>String</code> to do its dirty work.  It&#8217;s smart, but it means that <code>Character</code>s are as expensive as <code>String</code>s<sup data-fn="a966f782-5d20-411c-a04b-7b82986b6617" class="fn"><a href="#a966f782-5d20-411c-a04b-7b82986b6617" id="a966f782-5d20-411c-a04b-7b82986b6617-link">2</a></sup>.</p>



<p>Swift has no direct equivalent to the <code>char</code> type that many other languages have (i.e. an ASCII character; a byte).  The closest thing is <code>UInt8</code> (which is why you&#8217;ll often see <code>[UInt8]</code> or <code>UnsafeMutableBufferPointer&lt;UInt8></code> or similar when dealing with raw memory or C/C++ APIs).</p>



<p>The takeaway is:  don&#8217;t treat <code>Character</code> like <code>char</code>.  They are very different.  <code>Character</code> is much more expensive, in both memory and CPU usage.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ Note that the quoted size of 16 bytes is <em>not</em> necessarily the full size of a <code>Character</code> or <code>String</code>.  That includes a <em>small</em> subsection available for storing the actual string data, if that data happens to be very small.  If it&#8217;s not, then <code>String</code> makes a <em>separate</em> memory allocation for it.  That second allocation is always <em>at least</em> 16 bytes too.</p>



<p>The situation is even more complicated for <code>NSString</code>s bridged from Objective-C.</p>
</div></div>



<h1 class="wp-block-heading">How types compose into structs, classes, and actors</h1>



<p><em>Generally</em>, the rules are:</p>



<ul class="wp-block-list">
<li><em>Alignment</em> is the greatest of the components&#8217; alignments.</li>



<li><em>Stride</em> is the [contiguous] size padded up &#8211; if necessary &#8211; to satisfy the alignment.</li>



<li><em>Size</em> is complicated. 😝</li>
</ul>



<p>Let&#8217;s start with a simple example:</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">struct</span><span style="color: #000000"> </span><span style="color: #267F99">Composite</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> a: </span><span style="color: #267F99">Int64</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> b: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>This <code>Composite</code> struct has a <em>nominal</em> size of twelve bytes &#8211; just the sum of its components.</p>



<p>Its components have alignment requirements of eight and four, respectively.  The greatest of those is eight, so that is the overall struct&#8217;s alignment.</p>



<p>Twelve is not a multiple of eight, so four bytes of padding are added to fix that, making the stride (the effective size) sixteen bytes.</p>



<p>But what happens if we change the order of the stored properties?</p>



<h2 class="wp-block-heading">Contiguous Size depends on stored property order</h2>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">struct</span><span style="color: #000000"> </span><span style="color: #267F99">CompositeB</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> b: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> a: </span><span style="color: #267F99">Int64</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>You might think this has no effect &#8211; after all, the struct is still storing the same things; what difference does the order make?</p>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-right" data-align="right">Type</th><th class="has-text-align-center" data-align="center">Nominal Size</th><th class="has-text-align-center" data-align="center">Contiguous Size</th><th class="has-text-align-center" data-align="center">Alignment</th><th class="has-text-align-center" data-align="center">Actual Size (Stride)</th><th class="has-text-align-center" data-align="center">Internal Padding</th><th class="has-text-align-center" data-align="center">Trailing Padding</th></tr></thead><tbody><tr><td class="has-text-align-right" data-align="right">Composite</td><td class="has-text-align-center" data-align="center">12</td><td class="has-text-align-center" data-align="center">12</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">4</td></tr><tr><td class="has-text-align-right" data-align="right">CompositeB</td><td class="has-text-align-center" data-align="center">12</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">0</td></tr></tbody></table></figure>



<p>For better or worse, Swift uses declaration order for the in-memory order of stored properties<sup data-fn="06c81bdc-8a1d-45ef-ba68-206050b9acd3" class="fn"><a href="#06c81bdc-8a1d-45ef-ba68-206050b9acd3" id="06c81bdc-8a1d-45ef-ba68-206050b9acd3-link">3</a></sup>.  And that can influence where padding goes.</p>



<p>In the case of our modified struct, <code>CompositeB</code>, the memory layout procedure is basically:</p>



<ol class="wp-block-list">
<li>Place the first item.  That&#8217;s an <code>Int32</code>, so it takes four bytes.  It requires four byte alignment, so the struct now requires [at least] four byte alignment.</li>



<li>Place the second item.  That&#8217;s an <code>Int64</code>.  It takes eight bytes.  It requires <em>eight</em> byte alignment.  So it cannot be placed immediately after the first item, as that would be an offset of and therefore alignment of four, which is not a multiple of eight.  So four bytes of padding are added, in-between the two items.<br><br>And the alignment requirement of the overall struct bumps up to eight, as well.</li>
</ol>



<p>The net result is that while the effective size is unchanged (at sixteen bytes), the Contiguous Size <em>has</em> changed &#8211; before it was technically just twelve bytes, but now it&#8217;s the full sixteen.  There&#8217;s still four bytes of padding in there that technically don&#8217;t matter and aren&#8217;t used, but because they&#8217;re now in the middle instead of at the end, they&#8217;re harder for the compiler to ignore.</p>



<h3 class="wp-block-heading">Trailing padding is better than internal padding</h3>



<p>In this specific example, this change doesn&#8217;t really matter.  The code generated for copying the struct will probably just use two load and two store instructions anyway, one for each stored property, so it doesn&#8217;t really matter where the padding is.  However, if the struct were bigger &#8211; more and/or larger stored properties &#8211; then copy might be implement as a call to <code>memcpy</code><sup data-fn="7bdf4f15-e127-4de0-9256-abf550dbb5b0" class="fn"><a href="#7bdf4f15-e127-4de0-9256-abf550dbb5b0" id="7bdf4f15-e127-4de0-9256-abf550dbb5b0-link">4</a></sup>.  That call won&#8217;t bother including any <em>trailing</em> padding because that&#8217;s easy to omit &#8211; just stop copying early &#8211; but it&#8217;ll have to copy the <em>internal</em> padding bytes even though their contents are irrelevant.  So it wastes time.</p>



<p>How <em>often</em> this manifests as a noticeable performance difference is much harder to say.  Probably you shouldn&#8217;t stress too much about this.  However, that doesn&#8217;t mean you can ignore stored property ordering, because…</p>



<h2 class="wp-block-heading">Actual Size (Stride) also depends on stored property order</h2>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">struct</span><span style="color: #000000"> </span><span style="color: #267F99">Composite2</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> a: </span><span style="color: #267F99">Int64</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> b: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> c: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #0000FF">struct</span><span style="color: #000000"> </span><span style="color: #267F99">Composite2B</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> b: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> a: </span><span style="color: #267F99">Int64</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> c: </span><span style="color: #267F99">Int32</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-right" data-align="right">Type</th><th class="has-text-align-center" data-align="center">Nominal Size</th><th class="has-text-align-center" data-align="center">Contiguous Size</th><th class="has-text-align-center" data-align="center">Alignment</th><th class="has-text-align-center" data-align="center">Actual Size (Stride)</th><th class="has-text-align-center" data-align="center">Internal Padding</th><th class="has-text-align-center" data-align="center">Trailing Padding</th></tr></thead><tbody><tr><td class="has-text-align-right" data-align="right">Composite2</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Composite2B</td><td class="has-text-align-center" data-align="center">16</td><td class="has-text-align-center" data-align="center">20</td><td class="has-text-align-center" data-align="center">8</td><td class="has-text-align-center" data-align="center">24</td><td class="has-text-align-center" data-align="center">4</td><td class="has-text-align-center" data-align="center">4</td></tr></tbody></table></figure>



<p>Oh no!  Storing the exact same data in the &#8216;wrong&#8217; order has increased the actual memory usage by 50%!</p>



<p>It&#8217;s the same reason as for the simpler case covered earlier &#8211; every individual stored property must be stored with correct alignment, which means you can&#8217;t put an <code>Int64</code> immediately after a single <code>Int32</code>.  Having to put four bytes of padding in-between means your overall size (twenty bytes) isn&#8217;t a multiple of the overall alignment requirement (eight) so <em>another</em> four bytes of padding have to be added at the end.</p>



<p>Now, this doesn&#8217;t <em>always</em> matter.  If you only have a handful of instances of <code>Composite2B</code> in your program at any one time, the wasted memory will be insignificant.  But if you have many then it can add up to a significant cost.  So be on the lookout for this problem for any data types you use in large numbers.</p>



<p>Fortunately, changing the order of stored properties is always source-compatible, and is binary-compatible too (a.k.a. &#8220;ABI-compatible&#8221;) for <a href="https://github.com/apple/swift/blob/main/docs/LibraryEvolution.rst#classes" data-wpel-link="external" target="_blank" rel="external noopener">classes &amp; actors</a>, as well as <a href="https://github.com/apple/swift/blob/main/docs/LibraryEvolution.rst#structs" data-wpel-link="external" target="_blank" rel="external noopener">non-frozen structs</a>.  So even if you don&#8217;t catch the problem immediately, you might still be able to fix it.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️ Although we&#8217;ve been looking at structs here, know that this all applies similarly to classes &amp; actors.  The main difference is that every class or actor &#8211; in fact, any reference type &#8211; is <em>at least</em> sixteen bytes irrespective of what stored properties it has.  Its alignment is likewise always <em>at least</em> sixteen bytes<sup data-fn="69e5ba4a-f757-497e-9fb7-1f1652436f33" class="fn"><a href="#69e5ba4a-f757-497e-9fb7-1f1652436f33" id="69e5ba4a-f757-497e-9fb7-1f1652436f33-link">5</a></sup>.  So the padding problems, and wasted space that result from them, tend to be even worse with classes &amp; actors.</p>
</div></div>



<h2 class="wp-block-heading">Bools are bytes, not bits</h2>



<p>In principle a boolean uses just a single bit of memory &#8211; true or false, 1 or 0.  Unfortunately, high-level languages like Swift tend to think of everything as <em>bytes</em>, not bits, and the smallest number of bytes is one &#8211; <em>eight</em> bits.</p>



<p>We saw this in the beginning, with <code>Bool</code> taking a whole byte even though it only uses an eighth of that memory.</p>



<p>Unfortunately, this carries over even to collections of <code>Bool</code>s.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">struct</span><span style="color: #000000"> </span><span style="color: #267F99">ManyBooleans</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> a: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> b: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> c: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> d: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> e: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> f: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> g: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">let</span><span style="color: #000000"> h: </span><span style="color: #267F99">Bool</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<p>In some languages, <code>ManyBooleans</code> would take up just one byte.  It has eight booleans, which need eight bits, which can be packed together into a single byte.  Perfect!</p>



<p>Unfortunately, Swift does not do that currently<sup data-fn="704b9877-db92-45a0-b3a3-07dec843e615" class="fn"><a href="#704b9877-db92-45a0-b3a3-07dec843e615" id="704b9877-db92-45a0-b3a3-07dec843e615-link">6</a></sup>.  In Swift, <code>ManyBooleans</code> is eight bytes.  It has an alignment of just one, so at least it never wastes any space with padding.  Nonetheless, it still takes up <em>eight times</em> as much memory as it needs to. 😢</p>



<p>This applies similarly to collections of <code>Bool</code>s, like <code>Array</code>s.  A <code>[Bool]</code> takes up one byte per entry, not one bit.  There is no native equivalent to C++&#8217;s <code><a href="https://en.cppreference.com/w/cpp/container/vector_bool" data-wpel-link="external" target="_blank" rel="external noopener">vector&lt;bool></a></code> in Swift (Swift does not support template specialisation in that sense), although <a href="https://github.com/apple/swift-collections" data-wpel-link="external" target="_blank" rel="external noopener">swift-collections</a> does contain <code><a href="https://swiftpackageindex.com/apple/swift-collections/main/documentation/bitcollections/bitarray" data-wpel-link="external" target="_blank" rel="external noopener">BitArray</a></code> (and <code><a href="https://swiftpackageindex.com/apple/swift-collections/main/documentation/bitcollections/bitset" data-wpel-link="external" target="_blank" rel="external noopener">BitSet</a></code>) collections that you can use manually (but you have to remember to use them!).</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>🎉 I want to call out that these bit-efficient collections were added through a <a href="https://summerofcode.withgoogle.com" data-wpel-link="external" target="_blank" rel="external noopener">Google Summer of Code</a> project, by <a href="https://forums.swift.org/u/MahanazAtiqullah/summary" data-wpel-link="external" target="_blank" rel="external noopener">Mahanaz Atiqullah</a> with mentoring by <a href="https://forums.swift.org/u/david_smith/summary" data-wpel-link="external" target="_blank" rel="external noopener">David Smith</a>, <a href="https://forums.swift.org/u/lorentey/summary" data-wpel-link="external" target="_blank" rel="external noopener">Karoy Lorentey</a>, and <a href="https://forums.swift.org/u/kylemacomber/summary" data-wpel-link="external" target="_blank" rel="external noopener">Kyle Macomber</a>.  See <a href="https://forums.swift.org/t/bit-array-and-bit-set-api-review-the-end-of-a-gsoc-project/51396/1" data-wpel-link="external" target="_blank" rel="external noopener">her project presentation</a> for details and some benchmark numbers showing that these specialised collections are not just much more memory efficient but <em>much</em> faster as well.</p>
</div></div>



<h2 class="wp-block-heading">…except when they&#8217;re not</h2>



<figure class="wp-block-table aligncenter"><table><thead><tr><th class="has-text-align-right" data-align="right">Type</th><th class="has-text-align-center" data-align="center">Nominal Size</th><th class="has-text-align-center" data-align="center">Contiguous Size</th><th class="has-text-align-center" data-align="center">Alignment</th><th class="has-text-align-center" data-align="center">Actual Size (Stride)</th><th class="has-text-align-center" data-align="center">Internal Padding</th><th class="has-text-align-center" data-align="center">Trailing Padding</th></tr></thead><tbody><tr><td class="has-text-align-right" data-align="right">Bool</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr><tr><td class="has-text-align-right" data-align="right">Optional&lt;Bool></td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">1</td><td class="has-text-align-center" data-align="center">0</td><td class="has-text-align-center" data-align="center">0</td></tr></tbody></table></figure>



<p>What witchcraft is this?!  We just saw that two <code>Bool</code>s do <em>not</em> share a byte in Swift, yet here we have conceptually two <code>Bool</code>s, and they&#8217;re doing exactly that!</p>



<p>This is because enums, basically.  They are a whole other kettle of fish.  I plan to do a follow-up post on their unique behaviour when it comes to memory layout.</p>


<ol class="wp-block-footnotes"><li id="13cd788d-5855-4a1e-a1bd-5d8bf2c204ed">For <em>most</em> purposes <em>in memory</em>.  It may be <em>possible</em> to pack the type into a smaller space (even without using formal compression) such as for serialisation into a file or to send over a network, but in general you can&#8217;t use the type in a Swift program if it&#8217;s not properly padded to its stride and correctly aligned. <a href="#13cd788d-5855-4a1e-a1bd-5d8bf2c204ed-link" aria-label="Jump to footnote reference 1">↩︎</a></li><li id="a966f782-5d20-411c-a04b-7b82986b6617">Potentially even <em>more</em> expensive due to the indirection, although most <code>Character</code> APIs are inlinable and so tend to get compiled out by the optimiser. <a href="#a966f782-5d20-411c-a04b-7b82986b6617-link" aria-label="Jump to footnote reference 2">↩︎</a></li><li id="06c81bdc-8a1d-45ef-ba68-206050b9acd3"><a href="https://forums.swift.org/t/optimal-stored-property-packing/70327" data-wpel-link="external" target="_blank" rel="external noopener">It generally doesn&#8217;t have to though</a>, which opens up the possibility that Swift will improve this behaviour in future. <a href="#06c81bdc-8a1d-45ef-ba68-206050b9acd3-link" aria-label="Jump to footnote reference 3">↩︎</a></li><li id="7bdf4f15-e127-4de0-9256-abf550dbb5b0">The reasoning is complicated and subject to the whims of the compiler&#8217;s optimiser, but it factors in considerations such as the code size (of a single function call to <code>memcpy</code> vs potentially many separate load &amp; store instructions) and performance (at some point it becomes faster to just copy all the bytes together than copy every stored property&#8217;s bytes individually). <a href="#7bdf4f15-e127-4de0-9256-abf550dbb5b0-link" aria-label="Jump to footnote reference 4">↩︎</a></li><li id="69e5ba4a-f757-497e-9fb7-1f1652436f33">This is actually a consequence of how malloc is implemented on virtually all platforms &#8211; and certainly all of Apple&#8217;s &#8211; which is to return memory allocations that are at least sixteen bytes in size, and usually a power of two (so 16, 32, 64, 128, etc).  So your class might nominally only need 65 bytes of memory per instance, but it might end up using 128.  Which can make classes &amp; actors even <em>more</em> problematic regarding memory size and waste, than structs &amp; enums &#8211; a topic for a follow-up post, perhaps. <a href="#69e5ba4a-f757-497e-9fb7-1f1652436f33-link" aria-label="Jump to footnote reference 5">↩︎</a></li><li id="704b9877-db92-45a0-b3a3-07dec843e615"><a href="https://forums.swift.org/t/optimal-stored-property-packing/70327/5" data-wpel-link="external" target="_blank" rel="external noopener">It <em>could</em></a>, though, in future. <a href="#704b9877-db92-45a0-b3a3-07dec843e615-link" aria-label="Jump to footnote reference 6">↩︎</a></li></ol>


<h1 class="wp-block-heading">Appendices</h1>



<h2 class="wp-block-heading" id="helper-functions">Helper functions</h2>



<p>This post used the following core code for the data presented in the tables.  It&#8217;s pretty hacky &#8211; it doesn&#8217;t work correctly for all types, as the inline comments note, but it is sufficient for the relatively simple examples shown in this post.</p>



<div class="wp-block-kevinbatdorf-code-block-pro padding-disabled" data-code-block-pro-font-family="" style="font-size:.875rem;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #008000">// Table header</span></span>
<span class="line"><span style="color: #795E26">print</span><span style="color: #000000">(</span><span style="color: #A31515">&quot;Type&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Nominal Size&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Contiguous Size&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Alignment&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Actual Size (Stride)&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Internal padding&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #A31515">&quot;Trailing Padding&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">      </span><span style="color: #001080">separator</span><span style="color: #000000">: </span><span style="color: #A31515">&quot;</span><span style="color: #EE0000">\t</span><span style="color: #A31515">&quot;</span><span style="color: #000000">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #008000">// Table row</span></span>
<span class="line"><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">sizeOf</span><span style="color: #000000">&lt;</span><span style="color: #267F99">T</span><span style="color: #000000">&gt;(</span><span style="color: #001080">_</span><span style="color: #000000"> </span><span style="color: #001080">value</span><span style="color: #000000">: </span><span style="color: #0070C1">T</span><span style="color: #000000">) -&gt; </span><span style="color: #001080">Int</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #0070C1">T</span><span style="color: #000000">&gt;.</span><span style="color: #001080">size</span></span>
<span class="line"><span style="color: #000000">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #001080">func</span><span style="color: #000000"> </span><span style="color: #795E26">printLayout</span><span style="color: #000000">&lt;</span><span style="color: #267F99">T</span><span style="color: #000000">&gt;(</span><span style="color: #0000FF">of</span><span style="color: #000000"> </span><span style="color: #001080">type</span><span style="color: #000000">: </span><span style="color: #0070C1">T</span><span style="color: #000000">.</span><span style="color: #001080">Type</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">                    </span><span style="color: #001080">example</span><span style="color: #000000">: </span><span style="color: #0070C1">T</span><span style="color: #000000">? = </span><span style="color: #001080">nil</span><span style="color: #000000">) {</span></span>
<span class="line"><span style="color: #000000">    let </span><span style="color: #001080">nominalSize</span><span style="color: #000000"> = </span><span style="color: #001080">if</span><span style="color: #000000"> </span><span style="color: #001080">let</span><span style="color: #000000"> </span><span style="color: #001080">example</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #008000">// Note: doesn&#39;t handle recursive types (nested structs, classes, actors, enums, etc).</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #008000">//       Also not correct for primitive types (e.g. integers).</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">Mirror</span><span style="color: #000000">(</span><span style="color: #001080">reflecting</span><span style="color: #000000">: </span><span style="color: #267F99">example</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">            .children</span></span>
<span class="line"><span style="color: #000000">            .lazy</span></span>
<span class="line"><span style="color: #000000">            </span><span style="color: #008000">// Have to force open the existential because Swift won&#39;t implicitly open Any in Swift 5 mode.</span></span>
<span class="line"><span style="color: #000000">            </span><span style="color: #008000">// https://forums.swift.org/t/getting-the-size-of-any-value/62843/4</span></span>
<span class="line"><span style="color: #000000">            </span><span style="color: #008000">// https://github.com/apple/swift-evolution/blob/main/proposals/0352-implicit-open-existentials.md#avoid-opening-when-the-existential-type-satisfies-requirements-in-swift-5</span></span>
<span class="line"><span style="color: #000000">            .map { </span><span style="color: #795E26">_openExistential</span><span style="color: #000000">(</span><span style="color: #001080">$0</span><span style="color: #000000">.</span><span style="color: #001080">value</span><span style="color: #000000">, </span><span style="color: #001080">do</span><span style="color: #000000">: </span><span style="color: #001080">sizeOf</span><span style="color: #000000">) }</span></span>
<span class="line"><span style="color: #000000">            .reduce(</span><span style="color: #001080">into:</span><span style="color: #000000"> </span><span style="color: #098658">0</span><span style="color: #000000">, +=)</span></span>
<span class="line"><span style="color: #000000">    } </span><span style="color: #001080">else</span><span style="color: #000000"> {</span></span>
<span class="line"><span style="color: #000000">        MemoryLayout&lt;T&gt;.</span><span style="color: #001080">size</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #795E26">print</span><span style="color: #000000">(</span><span style="color: #A31515">&quot;</span><span style="color: #EE0000">\(</span><span style="color: #A31515">type):&quot;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">nominalSize</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.size,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.alignment,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.stride,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.size - </span><span style="color: #001080">nominalSize</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.stride - </span><span style="color: #001080">MemoryLayout</span><span style="color: #000000">&lt;</span><span style="color: #001080">T</span><span style="color: #000000">&gt;.size,</span></span>
<span class="line"><span style="color: #000000">          </span><span style="color: #001080">separator</span><span style="color: #000000">: </span><span style="color: #A31515">&quot;</span><span style="color: #EE0000">\t</span><span style="color: #A31515">&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/a-brief-introduction-to-type-memory-layout-in-swift/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7803</post-id>	</item>
	</channel>
</rss>
