<?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>NSData &#8211; Wade Tregaskis</title>
	<atom:link href="https://wadetregaskis.com/tags/nsdata/feed/" rel="self" type="application/rss+xml" />
	<link>https://wadetregaskis.com</link>
	<description></description>
	<lastBuildDate>Sun, 05 May 2024 19:49:03 +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>NSData &#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>URLSession performance for reading a byte stream</title>
		<link>https://wadetregaskis.com/urlsession-performance-for-reading-a-byte-stream/</link>
					<comments>https://wadetregaskis.com/urlsession-performance-for-reading-a-byte-stream/#respond</comments>
		
		<dc:creator><![CDATA[]]></dc:creator>
		<pubDate>Fri, 03 May 2024 23:52:00 +0000</pubDate>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Benchmarked]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[NSData]]></category>
		<category><![CDATA[Swift]]></category>
		<category><![CDATA[URLSession]]></category>
		<category><![CDATA[withUnsafeBytes]]></category>
		<guid isPermaLink="false">https://wadetregaskis.com/?p=8006</guid>

					<description><![CDATA[What&#8217;s the best way to read a stream of bytes with URLSession? That&#8217;s the simple question I set out to answer. I wrote some benchmarks. They read a 128 MiB file and perform a contrived aggregation of its content bytes (a joking &#8220;hash&#8221; of them, merely to ensure the actual reads aren&#8217;t optimised out). ⚠️&#8230; <a class="read-more-link" href="https://wadetregaskis.com/urlsession-performance-for-reading-a-byte-stream/" data-wpel-link="internal">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>What&#8217;s the best way to read a stream of bytes with <code><a href="https://developer.apple.com/documentation/foundation/urlsession" data-wpel-link="external" target="_blank" rel="external noopener">URLSession</a></code>? That&#8217;s the simple question I set out to answer. I wrote <a href="https://github.com/wadetregaskis/Swift-Benchmarks/blob/main/Benchmarks/URLSession/URLSession.swift" data-wpel-link="external" target="_blank" rel="external noopener">some benchmarks</a>. They read a 128 MiB file and perform a contrived aggregation of its content bytes (a joking &#8220;hash&#8221; of them, merely to ensure the actual reads aren&#8217;t optimised out).</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ In a nutshell, the results here demonstrate the <em>best-case</em> performance for each of the methods evaluated.  These benchmarks are very simple, which makes them relatively easy for the Swift compiler to optimise well.  In less trivial, real-world code, the optimiser might not do so great.  So these benchmarks and their results are merely one collective data point in the bigger picture of just how the heck to read files efficiently.  </p>
</div></div>



<p>There&#8217;s two key decisions you must make:  which specific <code>URLSession</code> API will you use, and how will you access the bytes themselves.</p>



<h2 class="wp-block-heading">Measurements</h2>



<p>Each benchmark was run a hundred times or for 30 seconds (whichever limit was hit first).  I&#8217;m highlighting here just the medians (in general there wasn&#8217;t much variation anyway), but you can dig into the other percentiles &amp; metrics via the disclosure triangles, if you like.</p>



<p>I&#8217;m pretty sure the reads were all served out of the kernel&#8217;s in-memory file system cache, judging by the lack of SSD read I/O reported by <a href="https://bjango.com/mac/istatmenus/" data-wpel-link="external" target="_blank" rel="external noopener">iStat Menus</a>.  But I didn&#8217;t go out of my way to verify this.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ &#8220;Peak RAM&#8221; is as reported by the <a href="https://github.com/ordo-one/package-benchmark" data-wpel-link="external" target="_blank" rel="external noopener">Benchmark</a> package, based on (if I understand it correctly) periodic sampling of the process RSS.  As such it&#8217;s not necessarily completely accurate, due to the potential to miss brief peaks.</p>
</div></div>



<h3 class="wp-block-heading">M2 MacBook Air</h3>



<figure class="wp-block-table aligncenter"><table><thead><tr><th>Method</th><th class="has-text-align-right" data-align="right">Wall time (ms)</th><th class="has-text-align-right" data-align="right">CPU time (ms)</th><th class="has-text-align-right" data-align="right">Throughput (MiB/s)</th><th class="has-text-align-right" data-align="right">Peak RAM (MB)</th></tr></thead><tbody><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767351-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes(from:)</a></code> and for loop</td><td class="has-text-align-right" data-align="right">79</td><td class="has-text-align-right" data-align="right">138</td><td class="has-text-align-right" data-align="right">1,620</td><td class="has-text-align-right" data-align="right">91</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767351-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/urlsession/asyncbytes/3767347-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">79</td><td class="has-text-align-right" data-align="right">138</td><td class="has-text-align-right" data-align="right">1,620</td><td class="has-text-align-right" data-align="right">84</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and for loop</td><td class="has-text-align-right" data-align="right">605</td><td class="has-text-align-right" data-align="right">641</td><td class="has-text-align-right" data-align="right">212</td><td class="has-text-align-right" data-align="right">265</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">60</td><td class="has-text-align-right" data-align="right">95</td><td class="has-text-align-right" data-align="right">2,133</td><td class="has-text-align-right" data-align="right">338</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">765</td><td class="has-text-align-right" data-align="right">800</td><td class="has-text-align-right" data-align="right">167</td><td class="has-text-align-right" data-align="right">262</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">750</td><td class="has-text-align-right" data-align="right">784</td><td class="has-text-align-right" data-align="right">171</td><td class="has-text-align-right" data-align="right">290</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with for loop</td><td class="has-text-align-right" data-align="right">560</td><td class="has-text-align-right" data-align="right">617</td><td class="has-text-align-right" data-align="right">229</td><td class="has-text-align-right" data-align="right">53</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">36</td><td class="has-text-align-right" data-align="right">75</td><td class="has-text-align-right" data-align="right">3,556</td><td class="has-text-align-right" data-align="right">26</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">719</td><td class="has-text-align-right" data-align="right">775</td><td class="has-text-align-right" data-align="right">178</td><td class="has-text-align-right" data-align="right">51</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">709</td><td class="has-text-align-right" data-align="right">765</td><td class="has-text-align-right" data-align="right">167</td><td class="has-text-align-right" data-align="right">45</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and for loop&nbsp;</td><td class="has-text-align-right" data-align="right">590</td><td class="has-text-align-right" data-align="right">630</td><td class="has-text-align-right" data-align="right">217</td><td class="has-text-align-right" data-align="right">442</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">57</td><td class="has-text-align-right" data-align="right">98</td><td class="has-text-align-right" data-align="right">2,246</td><td class="has-text-align-right" data-align="right">504</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">742</td><td class="has-text-align-right" data-align="right">783</td><td class="has-text-align-right" data-align="right">173</td><td class="has-text-align-right" data-align="right">470</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">742</td><td class="has-text-align-right" data-align="right">786</td><td class="has-text-align-right" data-align="right">173</td><td class="has-text-align-right" data-align="right">485</td></tr></tbody></table></figure>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Full results (raw text)</summary>
<pre class="wp-block-preformatted">bytewise read using bytes(from:) and for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      35 │      36 │      37 │      37 │      37 │      67 │      69 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      68 │      91 │      91 │      91 │      94 │      94 │      94 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    1841 │    1869 │    1883 │    1911 │    1925 │    1939 │    1953 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    1312 │    1332 │    1342 │    1362 │    1372 │    1382 │    1392 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      24 │      25 │      25 │      25 │      25 │      25 │      25 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     136 │     137 │     138 │     138 │     138 │     139 │     140 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      79 │      79 │      79 │      79 │      80 │      81 │      81 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using bytes(from:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      35 │      36 │      37 │      37 │      37 │      67 │      69 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      68 │      83 │      84 │      85 │      88 │      88 │      88 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    1840 │    1869 │    1897 │    1911 │    1925 │    1953 │    1967 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    1312 │    1332 │    1352 │    1362 │    1372 │    1392 │    1402 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      24 │      25 │      25 │      25 │      25 │      25 │      25 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     137 │     138 │     138 │     138 │     138 │     139 │     140 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      79 │      79 │      79 │      79 │      80 │      80 │      81 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      40 │      43 │      44 │      45 │      47 │      76 │      76 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     167 │     230 │     265 │     278 │     286 │     297 │     297 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      21 │      23 │      23 │      23 │      23 │      23 │      23 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     631 │     639 │     641 │     647 │     659 │     676 │     676 │      50 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     600 │     603 │     605 │     610 │     625 │     642 │     642 │      50 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      39 │      44 │      44 │      45 │      47 │      75 │      76 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     150 │     293 │     338 │     398 │     419 │     439 │     445 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │      11 │      11 │      11 │      11 │      11 │      11 │      11 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │       5 │       5 │       5 │       5 │       5 │       5 │       5 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      21 │      22 │      22 │      23 │      23 │      23 │      23 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │      79 │      93 │      95 │      96 │      98 │     106 │     110 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      49 │      59 │      60 │      61 │      62 │      68 │      71 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      41 │      43 │      44 │      45 │      47 │      77 │      77 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     145 │     228 │     262 │     279 │     292 │     296 │     296 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      22 │      22 │      23 │      23 │      23 │      23 │      23 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     782 │     794 │     800 │     805 │     806 │     816 │     816 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     750 │     760 │     765 │     771 │     773 │     783 │     783 │      40 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      41 │      44 │      44 │      45 │      47 │      77 │      77 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     165 │     254 │     290 │     338 │     353 │     361 │     361 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      22 │      22 │      22 │      23 │      23 │      23 │      23 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     771 │     777 │     784 │     789 │     792 │     796 │     796 │      40 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     738 │     742 │     750 │     756 │     758 │     760 │     760 │      40 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      34 │      35 │      36 │      36 │      37 │      69 │      69 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      52 │      52 │      53 │      57 │      57 │      57 │      57 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      26 │      26 │      27 │      27 │      27 │      27 │      27 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     616 │     616 │     617 │     617 │     617 │     620 │     620 │      54 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     559 │     559 │     560 │     560 │     560 │     564 │     564 │      54 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      47 │      51 │      53 │      55 │      57 │      87 │      87 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      22 │      26 │      26 │      27 │      27 │      27 │      27 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    6135 │    6147 │    6147 │    6147 │    6150 │    6150 │    6150 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    2046 │    2051 │    2051 │    2051 │    2051 │    2051 │    2051 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      35 │      35 │      35 │      35 │      35 │      35 │      35 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │      73 │      74 │      75 │      75 │      76 │      76 │      76 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      35 │      36 │      36 │      36 │      36 │      37 │      37 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      34 │      35 │      36 │      36 │      37 │      68 │      68 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      47 │      50 │      51 │      51 │      51 │      51 │      51 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      26 │      27 │      27 │      27 │      27 │      27 │      27 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     773 │     774 │     775 │     775 │     776 │     779 │     779 │      42 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     717 │     718 │     719 │     719 │     719 │     722 │     722 │      42 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      34 │      35 │      36 │      36 │      37 │      70 │      70 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      45 │      45 │      45 │      45 │      45 │      45 │      45 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      26 │      26 │      27 │      27 │      27 │      27 │      27 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     763 │     764 │     765 │     766 │     766 │     768 │     768 │      43 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     707 │     709 │     709 │     710 │     710 │     714 │     714 │      43 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and for loop <br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      39 │      43 │      44 │      47 │      50 │      79 │      79 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     378 │     410 │     442 │     471 │     496 │     528 │     528 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      27 │      27 │      28 │      28 │      28 │      28 │      28 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     624 │     627 │     630 │     632 │     634 │     640 │     640 │      51 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     587 │     589 │     590 │     594 │     597 │     601 │     601 │      51 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      38 │      43 │      45 │      46 │      48 │      76 │      76 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     394 │     462 │     504 │     525 │     547 │     583 │     587 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │       5 │       5 │       5 │       5 │       5 │       5 │       5 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │       3 │       3 │       3 │       3 │       3 │       3 │       3 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      27 │      27 │      28 │      28 │      28 │      28 │      28 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │      92 │      96 │      98 │     100 │     102 │     105 │     106 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      55 │      57 │      57 │      58 │      59 │      61 │      63 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      38 │      41 │      44 │      47 │      51 │      74 │      74 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     391 │     430 │     470 │     560 │     587 │     617 │     617 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      27 │      28 │      28 │      28 │      28 │      28 │      28 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     773 │     776 │     783 │     789 │     790 │     795 │     795 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     734 │     737 │     742 │     749 │     751 │     755 │     755 │      41 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      38 │      43 │      44 │      46 │      51 │      77 │      77 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     348 │     408 │     451 │     485 │     499 │     548 │     548 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      27 │      28 │      28 │      28 │      28 │      28 │      28 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     770 │     776 │     786 │     788 │     793 │     796 │     796 │      41 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     732 │     737 │     742 │     749 │     752 │     755 │     755 │      41 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛</pre>
</details>



<h3 class="wp-block-heading">10-core iMac Pro</h3>



<figure class="wp-block-table aligncenter"><table><thead><tr><th>Method</th><th class="has-text-align-right" data-align="right">Wall time (ms)</th><th class="has-text-align-right" data-align="right">CPU time (ms)</th><th class="has-text-align-right" data-align="right">Throughput (MiB/s)</th><th class="has-text-align-right" data-align="right">Peak RAM (MB)</th></tr></thead><tbody><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767351-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes(from:)</a></code> and for loop</td><td class="has-text-align-right" data-align="right">138</td><td class="has-text-align-right" data-align="right">250</td><td class="has-text-align-right" data-align="right">928</td><td class="has-text-align-right" data-align="right">54</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767351-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/urlsession/asyncbytes/3767347-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">139</td><td class="has-text-align-right" data-align="right">251</td><td class="has-text-align-right" data-align="right">921</td><td class="has-text-align-right" data-align="right">53</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and for loop</td><td class="has-text-align-right" data-align="right">953</td><td class="has-text-align-right" data-align="right">1,023</td><td class="has-text-align-right" data-align="right">134</td><td class="has-text-align-right" data-align="right">257</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">140</td><td class="has-text-align-right" data-align="right">208</td><td class="has-text-align-right" data-align="right">914</td><td class="has-text-align-right" data-align="right">344</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">1,181</td><td class="has-text-align-right" data-align="right">1,254</td><td class="has-text-align-right" data-align="right">108</td><td class="has-text-align-right" data-align="right">236</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/3767353-data" data-wpel-link="external" target="_blank" rel="external noopener">data(from:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">1,163</td><td class="has-text-align-right" data-align="right">1,233</td><td class="has-text-align-right" data-align="right">110</td><td class="has-text-align-right" data-align="right">232</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with for loop</td><td class="has-text-align-right" data-align="right">848</td><td class="has-text-align-right" data-align="right">964</td><td class="has-text-align-right" data-align="right">151</td><td class="has-text-align-right" data-align="right">40</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">56</td><td class="has-text-align-right" data-align="right">140</td><td class="has-text-align-right" data-align="right">2,286</td><td class="has-text-align-right" data-align="right">23</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">1,066</td><td class="has-text-align-right" data-align="right">1,181</td><td class="has-text-align-right" data-align="right">120</td><td class="has-text-align-right" data-align="right">35</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1411554-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:)</a></code> and an incremental delegate with <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">1,072</td><td class="has-text-align-right" data-align="right">1,185</td><td class="has-text-align-right" data-align="right">119</td><td class="has-text-align-right" data-align="right">43</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and for loop&nbsp;</td><td class="has-text-align-right" data-align="right">948</td><td class="has-text-align-right" data-align="right">1,026</td><td class="has-text-align-right" data-align="right">135</td><td class="has-text-align-right" data-align="right">375</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and for loop inside <code><a href="https://developer.apple.com/documentation/foundation/data/3139154-withunsafebytes" data-wpel-link="external" target="_blank" rel="external noopener">withUnsafeBytes</a></code></td><td class="has-text-align-right" data-align="right">137</td><td class="has-text-align-right" data-align="right">215</td><td class="has-text-align-right" data-align="right">934</td><td class="has-text-align-right" data-align="right">591</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/1780184-foreach" data-wpel-link="external" target="_blank" rel="external noopener">forEach</a></code></td><td class="has-text-align-right" data-align="right">1,179</td><td class="has-text-align-right" data-align="right">1,258</td><td class="has-text-align-right" data-align="right">109</td><td class="has-text-align-right" data-align="right">370</td></tr><tr><td><code><a href="https://developer.apple.com/documentation/foundation/urlsession/1410330-datatask" data-wpel-link="external" target="_blank" rel="external noopener">dataTask(with:completionHandler:)</a></code> and <code><a href="https://developer.apple.com/documentation/foundation/data/3126633-reduce" data-wpel-link="external" target="_blank" rel="external noopener">reduce</a></code></td><td class="has-text-align-right" data-align="right">1,176</td><td class="has-text-align-right" data-align="right">1,254</td><td class="has-text-align-right" data-align="right">109</td><td class="has-text-align-right" data-align="right">416</td></tr></tbody></table></figure>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Full results (raw text)</summary>
<pre class="wp-block-preformatted">bytewise read using bytes(from:) and for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      36 │      37 │      37 │      37 │      37 │      68 │      69 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      45 │      51 │      54 │      56 │      62 │      66 │      66 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    1952 │    2023 │    2051 │    2079 │    2093 │    2135 │    2135 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    1392 │    1442 │    1462 │    1482 │    1492 │    1522 │    1522 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      21 │      21 │      21 │      21 │      21 │      21 │      21 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     245 │     248 │     250 │     251 │     254 │     259 │     267 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     136 │     138 │     138 │     140 │     141 │     145 │     146 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using bytes(from:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      36 │      37 │      37 │      37 │      37 │      67 │      69 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      48 │      52 │      53 │      54 │      56 │      58 │      60 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    1953 │    2009 │    2037 │    2065 │    2079 │    2121 │    2121 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    1392 │    1432 │    1452 │    1472 │    1482 │    1512 │    1512 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      21 │      21 │      21 │      21 │      21 │      21 │      21 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     246 │     249 │     251 │     253 │     256 │     274 │     278 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     136 │     138 │     139 │     140 │     141 │     150 │     151 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      41 │      42 │      43 │      43 │      72 │      76 │      76 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     188 │     243 │     257 │     266 │     279 │     316 │     316 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      18 │      18 │      19 │      19 │      19 │      19 │      19 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1010 │    1015 │    1023 │    1031 │    1040 │    1060 │    1060 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     941 │     946 │     953 │     958 │     968 │     985 │     985 │      32 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      38 │      42 │      43 │      44 │      47 │      72 │      73 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     244 │     328 │     344 │     352 │     358 │     369 │     370 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │      11 │      11 │      11 │      11 │      11 │      11 │      11 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │       5 │       5 │       5 │       5 │       5 │       5 │       5 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      18 │      18 │      18 │      18 │      18 │      19 │      19 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     203 │     207 │     208 │     210 │     213 │     221 │     234 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     135 │     139 │     140 │     141 │     143 │     148 │     159 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      41 │      42 │      43 │      43 │      73 │      75 │      75 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     171 │     225 │     236 │     263 │     283 │     288 │     288 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      18 │      18 │      18 │      19 │      19 │      19 │      19 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1247 │    1250 │    1254 │    1266 │    1271 │    1284 │    1284 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1177 │    1179 │    1181 │    1194 │    1199 │    1211 │    1211 │      26 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using data(from:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      39 │      42 │      43 │      43 │      72 │      79 │      79 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     207 │     226 │     232 │     243 │     260 │     278 │     278 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      18 │      18 │      18 │      19 │      19 │      19 │      19 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1225 │    1228 │    1233 │    1243 │    1250 │    1269 │    1269 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1157 │    1160 │    1163 │    1172 │    1178 │    1198 │    1198 │      26 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with for loop<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      35 │      35 │      36 │      36 │      65 │      68 │      68 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      32 │      36 │      40 │      45 │      48 │      52 │      52 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      23 │      23 │      23 │      23 │      23 │      23 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     954 │     958 │     964 │     965 │     975 │     992 │     992 │      36 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     841 │     845 │     848 │     851 │     857 │     871 │     871 │      36 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      47 │      51 │      53 │      54 │      56 │      83 │      84 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      17 │      20 │      23 │      24 │      25 │      25 │      25 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │    5895 │    6067 │    6087 │    6099 │    6111 │    6123 │    6123 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │    1966 │    2024 │    2031 │    2035 │    2039 │    2043 │    2043 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      32 │      32 │      32 │      32 │      33 │      33 │      33 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     137 │     139 │     140 │     142 │     147 │     152 │     155 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │      55 │      55 │      56 │      56 │      58 │      60 │      62 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      35 │      35 │      36 │      36 │      65 │      69 │      69 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      29 │      33 │      35 │      37 │      39 │      41 │      41 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      23 │      23 │      23 │      23 │      23 │      23 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1169 │    1179 │    1181 │    1184 │    1190 │    1205 │    1205 │      29 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1056 │    1065 │    1066 │    1069 │    1074 │    1086 │    1086 │      29 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:) and an incremental delegate with reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      35 │      35 │      35 │      36 │      65 │      68 │      68 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │      30 │      35 │      43 │      46 │      48 │      52 │      52 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      23 │      23 │      23 │      23 │      23 │      23 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1176 │    1182 │    1185 │    1190 │    1198 │    1200 │    1200 │      28 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1061 │    1067 │    1072 │    1075 │    1080 │    1083 │    1083 │      28 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and for loop <br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      40 │      42 │      43 │      43 │      72 │      75 │      75 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     356 │     368 │     375 │     386 │     400 │     407 │     407 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      24 │      24 │      24 │      24 │      24 │      24 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1016 │    1023 │    1026 │    1032 │    1041 │    1048 │    1048 │      32 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     940 │     946 │     948 │     952 │     961 │     967 │     967 │      32 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and for loop inside withUnsafeBytes<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      40 │      42 │      43 │      43 │      44 │      74 │      74 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     370 │     580 │     591 │     599 │     607 │     613 │     614 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases                   │       5 │       5 │       5 │       5 │       5 │       5 │       5 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains                    │       3 │       3 │       3 │       3 │       3 │       3 │       3 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      23 │      24 │      24 │      24 │      24 │      24 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │     210 │     213 │     215 │     217 │     220 │     236 │     238 │     100 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │     133 │     135 │     137 │     138 │     140 │     153 │     154 │     100 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and forEach<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      41 │      42 │      42 │      43 │      71 │      75 │      75 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     332 │     364 │     370 │     384 │     415 │     418 │     418 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      24 │      24 │      24 │      24 │      24 │      24 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1243 │    1253 │    1258 │    1268 │    1270 │    1277 │    1277 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1164 │    1175 │    1179 │    1188 │    1190 │    1201 │    1201 │      26 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛<br><br>bytewise read using dataTask(with:completionHandler:) and reduce<br>╒════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕<br>│ Metric                     │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │<br>╞════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡<br>│ Malloc (total) (K)         │      40 │      42 │      42 │      43 │      72 │      75 │      75 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Memory (resident peak) (M) │     353 │     392 │     416 │     452 │     472 │     473 │     473 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Releases (K)               │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Retains (K)                │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │    4194 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Syscalls (total) (K)       │      23 │      24 │      24 │      24 │      24 │      24 │      24 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (total CPU) (ms)      │    1241 │    1250 │    1254 │    1266 │    1278 │    1281 │    1281 │      26 │<br>├────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤<br>│ Time (wall clock) (ms)     │    1164 │    1172 │    1176 │    1185 │    1195 │    1200 │    1200 │      26 │<br>╘════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛</pre>
</details>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>☝️ I didn&#8217;t include it in these initial results, but there&#8217;s also <code><a href="https://developer.apple.com/documentation/foundation/data/1780329-enumeratebytes" data-wpel-link="external" target="_blank" rel="external noopener">enumerateBytes</a></code>, carried over from <code>NSData</code>.  It performs identically to <code>withUnsafeBytes</code>.  However, it is officially deprecated (Apple claims that for-loops are the replacement, even though they&#8217;re an order of magnitude slower 🤨).</p>



<p>🤔 I also tried to test the <code>NSData</code> <code><a href="https://developer.apple.com/documentation/foundation/nsdata/1410616-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes</a></code> property, but no matter how it&#8217;s used, it always results in the benchmark crashing.  It seems like it is actually unusable from Swift due to a memory management bug in the bridging layer and/or Swift compiler…?</p>
</div></div>



<h2 class="wp-block-heading">Observations</h2>



<h3 class="wp-block-heading">Incremental reads + withUnsafeBytes is unequivocally the best method</h3>



<p>It&#8217;s dramatically faster than any other approach &#8211; both in wall time and overall CPU usage &#8211; <em>and</em> uses the least amount of memory by far.</p>



<p>Within the <code><a href="https://developer.apple.com/documentation/foundation/data" data-wpel-link="external" target="_blank" rel="external noopener">Data</a></code>-centric methods this doesn&#8217;t surprise me &#8211; with the incremental approach <code>URLSession</code> can just hand data back as it comes in, in whatever chunk sizes are most convenient.  In the other <code>Data</code>-based approaches it has to aggregate everything into one final contiguous blob.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>🤔 This is all assuming that <code>URLSession</code> never memory-maps files, which I did not actually verify but does seem to be the case based on the performance and behaviour.  This strikes me as very odd, however, because memory-mapping the files would very likely be significantly faster, in the cases where it has to provide the entire contents as a single <code>Data</code> instance.  And <code>Data</code> already supports memory-mapping a file, very easily.</p>



<p>Of course, if your use-case doesn&#8217;t involve local files, then memory-mapping probably doesn&#8217;t apply anyway (unless <code>URLSession</code> uses a disk cache and the file is already in the cache &#8211; but I don&#8217;t know if it supports that).</p>
</div></div>



<h4 class="wp-block-heading">Implementation note</h4>



<p>I utilised the incremental API by basically adapting it to invoke a closure (shown below), mainly because it made it easier to then test different byte enumeration approaches within it, but the results should hold for typical implementations of <code><a href="https://developer.apple.com/documentation/foundation/urlsessiondatadelegate" data-wpel-link="external" target="_blank" rel="external noopener">URLSessionDataDelegate</a></code>.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<p>⚠️ This isn&#8217;t a robust implementation; it&#8217;s not suitable for use in a real program, merely sufficient for this very specific application in these benchmarks. It doesn&#8217;t communicate failures correctly, behaves very poorly if misused (e.g. by using it for more than one operation), naively blocks the thread that&#8217;s awaiting the data, etc. Please don&#8217;t use it as-is, but feel free to evolve it into a real solution for your own uses.</p>
</div></div>



<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)"><span role="button" tabindex="0" data-code="class IncrementalDataDelegate: NSObject, URLSessionDataDelegate {
    private let task: URLSessionTask
    private let handler: (Data) -&gt; ()
    private let done = NSCondition()

    init(_ task: URLSessionTask,
         handler: @escaping (Data) -&gt; ()) {
        self.task = task
        self.handler = handler
        super.init()
    }

    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        precondition(self.task == dataTask)
        self.handler(data)
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: (any Error)?) {
        precondition(self.task == task)

        if let error {
            preconditionFailure(&quot;Error: \(error)&quot;)
        }

        self.done.broadcast()
    }

    func wait() {
        self.done.wait()
    }
}" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">IncrementalDataDelegate</span><span style="color: #000000">: NSObject, URLSessionDataDelegate {</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">private</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> task: URLSessionTask</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">private</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> handler: (Data) -&gt; ()</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">private</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> done = </span><span style="color: #795E26">NSCondition</span><span style="color: #000000">()</span></span>
<span class="line"></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #0000FF">init</span><span style="color: #000000">(</span><span style="color: #795E26">_</span><span style="color: #000000"> </span><span style="color: #001080">task</span><span style="color: #000000">: URLSessionTask,</span></span>
<span class="line"><span style="color: #000000">         </span><span style="color: #795E26">handler</span><span style="color: #000000">: </span><span style="color: #0000FF">@escaping</span><span style="color: #000000"> (Data) -&gt; ()) {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">task</span><span style="color: #000000"> = task</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">handler</span><span style="color: #000000"> = handler</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #0000FF">super</span><span style="color: #000000">.</span><span style="color: #0000FF">init</span><span style="color: #000000">()</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: #0000FF">func</span><span style="color: #000000"> </span><span style="color: #795E26">urlSession</span><span style="color: #000000">(</span><span style="color: #795E26">_</span><span style="color: #000000"> </span><span style="color: #001080">session</span><span style="color: #000000">: URLSession, </span><span style="color: #795E26">dataTask</span><span style="color: #000000">: URLSessionDataTask, </span><span style="color: #795E26">didReceive</span><span style="color: #000000"> </span><span style="color: #001080">data</span><span style="color: #000000">: Data) {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">precondition</span><span style="color: #000000">(</span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">task</span><span style="color: #000000"> == dataTask)</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #795E26">handler</span><span style="color: #000000">(data)</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: #0000FF">func</span><span style="color: #000000"> </span><span style="color: #795E26">urlSession</span><span style="color: #000000">(</span><span style="color: #795E26">_</span><span style="color: #000000"> </span><span style="color: #001080">session</span><span style="color: #000000">: URLSession, </span><span style="color: #795E26">task</span><span style="color: #000000">: URLSessionTask, </span><span style="color: #795E26">didCompleteWithError</span><span style="color: #000000"> </span><span style="color: #001080">error</span><span style="color: #000000">: (any </span><span style="color: #267F99">Error</span><span style="color: #000000">)?) {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #795E26">precondition</span><span style="color: #000000">(</span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">task</span><span style="color: #000000"> == task)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #AF00DB">if</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> error {</span></span>
<span class="line"><span style="color: #000000">            </span><span style="color: #795E26">preconditionFailure</span><span style="color: #000000">(</span><span style="color: #A31515">&quot;Error: </span><span style="color: #0000FF">\(</span><span style="color: #000000FF">error</span><span style="color: #0000FF">)</span><span style="color: #A31515">&quot;</span><span style="color: #000000">)</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: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">done</span><span style="color: #000000">.</span><span style="color: #795E26">broadcast</span><span style="color: #000000">()</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: #0000FF">func</span><span style="color: #000000"> </span><span style="color: #795E26">wait</span><span style="color: #000000">() {</span></span>
<span class="line"><span style="color: #000000">        </span><span style="color: #0000FF">self</span><span style="color: #000000">.</span><span style="color: #001080">done</span><span style="color: #000000">.</span><span style="color: #795E26">wait</span><span style="color: #000000">()</span></span>
<span class="line"><span style="color: #000000">    }</span></span>
<span class="line"><span style="color: #000000">}</span></span></code></pre></div>



<h3 class="wp-block-heading"><a href="https://developer.apple.com/documentation/foundation/urlsession/asyncbytes" data-wpel-link="external" target="_blank" rel="external noopener">AsyncBytes</a> (<a href="https://developer.apple.com/documentation/foundation/urlsession/3767351-bytes" data-wpel-link="external" target="_blank" rel="external noopener">bytes(from:)</a>) is surprisingly not bad  &#8211; <em>in this specific case</em></h3>



<p>This was surprising to me because generally I&#8217;ve seen Swift&#8217;s <code><a href="https://developer.apple.com/documentation/swift/asyncsequence" data-wpel-link="external" target="_blank" rel="external noopener">AsyncSequence</a></code> stuff &#8211; especially for operating on individual bytes &#8211; being unusably slow and inefficient.  It&#8217;s actually what prompted me to do these benchmarks, because I stubbornly tried using <code>bytes(from:)</code> in a current project and the performance in that real app was god-awful.  These benchmarks demonstrate that it doesn&#8217;t necessarily <em>have</em> to be, and there&#8217;s something more complicated going on.  I&#8217;m yet to get to the bottom of that.</p>



<p>The problem seems to be that async code in general &#8211; but <em>especially</em> anything involving <code>AsyncSequence</code>s &#8211; is <em>terribly</em> dependent on the compiler&#8217;s optimiser.  If the optimiser does anything less than an astounding job on it, the performance can drop off a cliff.</p>



<p>So, while these results nominally recommend <code>bytes(from:)</code> as a decent way to use <code>URLSession</code> &#8211; being a respectable second-fastest in these benchmarks and noticeably easier to use than the fastest method &#8211; I&#8217;d be very cautious about it and test the performance early and often.</p>



<h3 class="wp-block-heading"><code>withUnsafeBytes</code> is <em>way</em> faster than &#8220;safe&#8221; access to <code>Data</code>&#8216;s contents</h3>



<p>It&#8217;s an order of magnitude faster an Apple Silicon, and &#8216;merely&#8217; seven to nine times faster on Intel.</p>



<p>This isn&#8217;t surprising &#8211; <code>Data</code>&#8216;s regular APIs involve actual <em>function calls</em> (if not also Objective-C message sends, depending on what exactly is being returned by <code>URLSession</code> (native <code>Data</code> or actual <code>NSData</code>) and how Swift imports <code>NSData</code> from Objective-C.  <code>withUnsafeBytes</code> provides basically direct memory access, with practically zero overhead.</p>



<p>However, it has one notable downside…</p>



<h3 class="wp-block-heading"><code>withUnsafeBytes</code> doubles the memory usage of the target <code>Data</code></h3>



<p>This surprised and disappointed me &#8211; <code>Data</code> is <em>supposed</em> to already be a contiguous array of bytes, internally, so accessing those bytes with <code>withUnsafeBytes</code> should be nothing more than returning a pointer to that internal storage.  But in at least some cases, it doesn&#8217;t &#8211; instead, it allocates a whole new memory allocation, copies its contents to that allocation, and then provides that instead (and releases it afterwards &#8211; so repeated calls will incur this overhead every time).</p>



<p>This isn&#8217;t a <em>huge</em> issue when the <code>Data</code>s in question are small &#8211; clearly it doesn&#8217;t hamper performance all that much, since it&#8217;s still the fastest way to access the bytes of even a 128 MiB <code>Data</code> &#8211; but it can be an issue when the <code>Data</code>s in question are not small.  If you run out of free RAM, the cost of the kernel&#8217;s in-memory compression or swapping is very likely going to cripple the performance far beyond the degrees seen here by using the slow APIs.</p>



<h3 class="wp-block-heading">Reading a file with URLSession takes more than one CPU core</h3>



<p>I pointedly included <em>both</em> wall time and CPU time to highlight that there&#8217;s multiple cores engaged simultaneously for a single read.  This isn&#8217;t surprising, but it&#8217;s important to remember if you&#8217;re doing lots of parallel I/O &#8211; you can&#8217;t just naively allocate one read operation per CPU core and expect linear scaling (notwithstanding CPU frequency scaling etc anyway).</p>



<p>Though, that&#8217;s generally true anyway because most systems don&#8217;t have enough disk or network I/O to keep up with the CPU anyway.</p>



<h3 class="wp-block-heading">for loops are faster than <code>forEach</code> &amp; <code>reduce</code></h3>



<p>This might surprise some folks.  It&#8217;s surely a bit of a sore point with functional programming dogmatists.  The difference isn&#8217;t <em>massive</em> &#8211; in these benchmarks it&#8217;s only about 20%.  Still, it&#8217;s measurable and noticeable.</p>



<p>I find the for-loop approach easier to write and read anyway, so IMO this is just another reason to favour that instead of functional programming styles.  But not a reason to unilaterally favour one over the other.</p>



<h3 class="wp-block-heading"><code>forEach</code> &amp; <code>reduce</code> perform the same</h3>



<p>Not surprising or news, but worth noting.  In principle the optimiser should reduce them to the exact same machine code in the end.</p>



<h3 class="wp-block-heading">Similar performance characteristics between [old] Intel Xeons and Apple Silicon</h3>



<p>The M2 was faster, of course, but maybe not <em>as much</em> faster than one would expect &#8211; at best only twice as fast, which (subjectively) feels underwhelming given Apple&#8217;s numerous manufacturing and design advantages versus my iMac Pro&#8217;s old Xeon.</p>



<p>What I mean, though, is that the relative performance of the different methods is about the same irrespective of the platform.  What&#8217;s good (or bad) on an M2 is likewise on an Intel CPU.  Which is worth appreciating &#8211; although x86 is rapidly fading into irrelevance, it&#8217;s not quite there yet, and it&#8217;s always unpleasant when optimising for one architecture has the opposite effect on another.</p>



<h3 class="wp-block-heading">You&#8217;re probably not going to be I/O limited on Apple SSDs</h3>



<p>(for a single read at a time, that is)</p>



<p>Even in the very best case shown here &#8211; and despite the <em>very</em> light workload these benchmarks impose, on the actual file data &#8211; the best throughput was merely ~3.6 GB/s.  That&#8217;s not bad, of course &#8211; only a few years ago that would have easily saturated any consumer storage device, even a big Thunderbolt RAID array of SSDs.  But these days most of Apple&#8217;s computers have PCIe 4, quad-lane SSDs that have read speeds of about 7 GB/s.</p>



<p><em>And</em>, this is all ignoring the fact that <em>actually</em> reading from an SSD has more overhead than merely reading from the kernel&#8217;s file system cache, as these benchmarks almost certainly did. So actual SSD read performance is very likely lower than what these benchmarks achieved.</p>



<p>That all said, it doesn&#8217;t necessarily take much to be I/O-limited &#8211; two or three concurrent reads, efficiently implemented, would probably do it.  Certainly if you just spin up an operation per CPU core and they all try to do I/O at once, even a rather inefficient implementation will hit the SSD&#8217;s limits.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wadetregaskis.com/urlsession-performance-for-reading-a-byte-stream/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">8006</post-id>	</item>
	</channel>
</rss>
