<?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/"
	>

<channel>
	<title>One Billion Row Challenge &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/one-billion-row-challenge/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Tue, 25 Feb 2025 21:49:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>MemoryBlocks For Speed: A Case Study</title>
		<link>https://blog.xojo.com/2025/02/26/memoryblocks-for-speed-a-case-study/</link>
		
		<dc:creator><![CDATA[Kem Tekinay]]></dc:creator>
		<pubDate>Wed, 26 Feb 2025 17:00:00 +0000</pubDate>
				<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[MemoryBlocks]]></category>
		<category><![CDATA[One Billion Row Challenge]]></category>
		<category><![CDATA[Preemptive Threads]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14534</guid>

					<description><![CDATA[A few years ago I held a session about MemoryBlocks at the Xojo Developer Conference where I discussed how, generally, MemoryBlocks (and Ptrs) should be&#8230;]]></description>
										<content:encoded><![CDATA[
<p>A few years ago I held a <a href="https://www.youtube.com/watch?v=3_uZ62mHCkw" target="_blank" rel="noreferrer noopener">session</a> about <code><a href="https://documentation.xojo.com/api/language/memoryblock.html#memoryblock" target="_blank" rel="noreferrer noopener">MemoryBlocks</a></code> at the Xojo Developer Conference where I discussed how, generally, <code>MemoryBlocks</code> (and <code>Ptrs</code>) should be avoided except for cases where you must use them, e.g., <code>Declare</code>, or when speed is absolutely critical. I offered this advice because a <code>MemoryBlock</code> can be tedious to work with, and can lead to hard-to-trace bugs.</p>



<p>But when you do need that extra boost, it&#8217;s an option to consider, and I recently came across a scenario where it made a huge difference.</p>



<h2 class="wp-block-heading">The (One Billion Row) Challenge</h2>



<p>This came about from <a href="https://forum.xojo.com/t/xojo1brc-xojo-one-billion-row-challenge/82844" target="_blank" rel="noreferrer noopener">a discussion of the &#8220;One Billion Row Challenge&#8221;</a> on the Xojo Forum, where a programmer is tasked with reading a billion rows of temperature data and consolidating it into statistics for each given city. Our friend <a href="https://forum.xojo.com/u/mike_d/summary" target="_blank" rel="noreferrer noopener">Mike D</a> started a project to demonstrate different techniques, and I eventually started <a href="https://github.com/ktekinay/Xojo-BRC" target="_blank" rel="noreferrer noopener">my own project</a>. Using <code>MemoryBlock</code>, <code>Ptr</code>, and preemptive threading, I was able to process a billion rows in roughly 8 seconds.</p>



<p>But that&#8217;s not the point of this post.</p>



<p>See, in order to process the data, you must first create it, which isn&#8217;t as straightforward as it seems.</p>



<h2 class="wp-block-heading">Creating The Data</h2>



<p>Each row of the data file takes the form &#8220;City;temp&#8221;, where &#8220;temp&#8221; is single-place decimal between -99.9 and 99.9. For purpose of limits, I used, arbitrarily, 413 random cities out of a list of all cities. The original code looked something like this where &#8220;bs&#8221; represents a <code>BinaryStream</code>:</p>



<pre class="wp-block-code"><code>Var r As New Random

For i As Integer = 1 To rowCount
  Var city As String = cities(r.InRange(0, cities.LastIndex))
  Var temp As Double = r.InRange(-999, 999) / 10.0

  bs.Write city + ";" + temp.ToString("#0.0") + EndOfLine
Next</code></pre>



<p>This was simple, easy, and slow. To generate the full billion rows took about 2.5 hours.</p>



<h2 class="wp-block-heading">Memory-Unblocking</h2>



<p>Upon investigation, I rediscovered what I already knew. Dealing with strings, both in conversion and concatenation, can be a bottleneck. I won&#8217;t go through all the iterations here, but nothing I tried made a significant difference. The only solution was to ditch strings entirely.</p>



<p>I started with creating a <code>MemoryBlock</code> &#8220;buffer&#8221; (&#8220;outMB&#8221;) of 1 MB with an associated <code>Ptr</code> (&#8220;outPtr&#8221;). (You can access the contents of a <code>MemoryBlock</code> through its methods, but those are function calls, which have an overhead. <code>Ptr</code> methods are operators that work with the bytes directly so they are faster.) The plan was to fill the buffer as much as I could, write it to the file, then start again at the top of the buffer.</p>



<p>Keeping a position index, I started with writing the city using <code>outMB.StringValue</code> since there is no equivalent <code>Ptr</code> method for this. Next, I plugged in the value of a semicolon with <code>outPtr.Byte(outMBIndex) = 59</code>.</p>



<p>Working with integers is faster than doubles, so I used a little math to plug in the temperature values directly using <code>If</code> statements and <code>outPtr.Byte</code>.</p>



<p>Finally, I used <code>outPtr.Byte(outMBIndex) = 10</code> to plug in the linefeed (ASCII 10).</p>



<p>The final code looked something like this:</p>



<pre class="wp-block-code"><code>Const kEOL As Integer = 10
Const kHyphen As Integer = 45
Const kDot As Integer = 46
Const kZero As Integer = 48
Const kSemicolon As Integer = 59

Var r As New Random

Var outMB As New MemoryBlock(1000000)
Var outPtr As Ptr = outMB

Var outMBIndex As Integer = 0

For row As Integer = 1 To rows
  Var cityIndex As Integer = r.InRange(0, cities.LastIndex)
  Var city As string = cities(cityIndex)
  Var cityBytes As Integer = city.Bytes

  If (outMBIndex + cityBytes + 10) &gt;= outMB.Size Then
    bs.Write outMB.StringValue(0, outMBIndex)
    outMBIndex = 0
  End If

  outMB.StringValue(outMBIndex, cityBytes) = city
  outMBIndex = outMBIndex + cityBytes

  outPtr.Byte(outMBIndex) = kSemicolon
  outMBIndex = outMBIndex + 1

  If r.InRange(0, 4) = 0 Then
    outPtr.Byte(outMBIndex) = kHyphen
    outMBIndex = outMBIndex + 1
  End If

  Var temp As Integer = r.InRange(0, 999)
  Var t1 As Integer = temp \ 100
  Var t2 As Integer = (temp \ 10) Mod 10
  Var t3 As Integer = temp Mod 10

  If t1 &lt;&gt; 0 Then
    outPtr.Byte(outMBIndex) = t1 + kZero
    outMBIndex = outMBIndex + 1
  End If

  outPtr.Byte(outMBIndex) = t2 + kZero
  outMBIndex = outMBIndex + 1

  outPtr.Byte(outMBIndex) = kDot
  outMBIndex = outMBIndex + 1

  outPtr.Byte(outMBIndex) = t3 + kZero
  outMBIndex = outMBIndex + 1

  outPtr.Byte(outMBIndex) = kEOL
  outMBIndex = outMBIndex + 1
next

If outMBIndex &lt;&gt; 0 Then
  bs.Write outMB.StringValue(0, outMBIndex)
End If</code></pre>



<p>This code is far longer, harder to follow, and difficult to maintain, which goes back to my original point of why <code>MemoryBlock</code> should be avoided.</p>



<p>It also generates one billion rows of data in about a minute (as opposed to 2.5 hours).</p>



<p>It&#8217;s nice to have the option.</p>



<p><em>Kem Tekinay is a Mac consultant and programmer who has been using Xojo since its first release to create custom solutions for clients. He is the author of the popular utilities <a href="http://www.mactechnologies.com/index.php?page=downloads#tftpclient" target="_blank" rel="noreferrer noopener">TFTP Client</a> and <a href="http://www.mactechnologies.com/index.php?page=downloads#regexrx" target="_blank" rel="noreferrer noopener">RegExRX</a> (both written with Xojo) and lives in Connecticut with his wife Lisa, and their cat.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
