<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Louis CAD dev blog]]></title><description><![CDATA[Louis CAD dev blog]]></description><link>https://blog.louiscad.com</link><generator>RSS for Node</generator><lastBuildDate>Sat, 12 Sep 2026 22:45:54 GMT</lastBuildDate><atom:link href="https://blog.louiscad.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Optimized Chessboard Pattern VectorDrawable in Kotlin]]></title><description><![CDATA[Trust me, I would have never been able to make such an efficient VectorDrawable with a designer tool like Sketch, Affinity Designer, or Adobe Illustrator.
This is the story of how I came to draw a chessboard pattern in VectorDrawable format using Kot...]]></description><link>https://blog.louiscad.com/optimized-chessboard-pattern-vectordrawable-in-kotlin</link><guid isPermaLink="true">https://blog.louiscad.com/optimized-chessboard-pattern-vectordrawable-in-kotlin</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[Android]]></category><category><![CDATA[SVG]]></category><category><![CDATA[Scripting]]></category><category><![CDATA[graphic design]]></category><dc:creator><![CDATA[Louis CAD]]></dc:creator><pubDate>Fri, 15 Jul 2022 14:16:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1657842794186/QIDfifQBG.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Trust me, I would have never been able to make such an efficient VectorDrawable with a designer tool like Sketch, Affinity Designer, or Adobe Illustrator.</strong></p>
<p>This is the story of how I came to draw a chessboard pattern in VectorDrawable format using Kotlin code, and how I ended up with a file <strong>5x smaller</strong> than I initially had. I had a lot of fun (and a bit of <code>fun</code>) doing it, so I want to share it with you.</p>
<h2 id="heading-why">Why</h2>
<p>For my Wear OS app that I'll publish on the Play Store soon, I need 3 variants of the same app:</p>
<ol>
<li>The debug variant</li>
<li>A minified variant that I can sign an update locally, for performance tests</li>
<li>The Play Store variant, that Google will sign with a key I don't have</li>
</ol>
<p>To easily distinguish these 3 apps on my test devices, I know 2 solutions:</p>
<ol>
<li>Adding a prefix letter/sign in the app name for the non-published variants</li>
<li>Have a visual mark on the icon of the non-published variants</li>
</ol>
<p>I used the first approach successfully in my previous job, but this time, I felt like trying the distinctive icon approach. I decided I would use a colored chessboard pattern for my debug and minified variants that I won't publish. Since the devices I'll regularly test on are all running Android 8 or later (API 26+), I can simply leverage adaptive icons where you can point to a buildType dependent resource for the background of the icon.</p>
<h2 id="heading-vectordrawables-in-a-nutshell">VectorDrawables in a nutshell</h2>
<p>Great! Now, I wanted to get the chessboard pattern. VectorDrawables which can be defined in XML and referenced in an adaptive icon sounded like the most straightforward option to get a nice result. Since a chessboard pattern is only made out of squares, I thought I would not need to use a vector graphics tool like Affinity Design, Sketch, Adobe Illustrator or Inkscape. Instead, I could write the drawing commands directly and ensure I'd <strong>get the most optimized result, decreasing the GPU/CPU load</strong>.</p>
<p>In my previous job, I have been learning a bit about how to write SVG path data myself so I could make the flag of Catalonia. <strong>It's actually very easy</strong> if you only do straight lines. It's only a few abbreviations/substitutes to learn for "move", "horizontal (line)", "vertical (line)", and "line". They are respectively "M", "H", "V", and "L" for absolute positions, and if you switch to lowercase, you have it for relative positions. And there's the <code>z</code> character that means "close the path with a straight line if needed".</p>
<p>For example, here's how to draw a rectangle of 2x1: <code>M0,0 H2 V1 H0 V0 z</code>. In plain English, here's what it means: Move to <code>0,0</code> (which is the top left corner) and start drawing, horizontal line to <code>2</code> (x axis), vertical line to <code>1</code> (y axis), horizontal line to <code>0</code> (x axis again), vertical line to <code>0</code> (y axis again), and finally close the path. <em>If you take a pen and follow these instructions on a piece of paper, you'll see you have just been drawing a 2x1 rectangle as advertised.</em> Note that the spaces are all optional, so we can write <code>M0,0H2V1H0V0z</code>, and save 5 bytes, which is 27.77% since we had 18 bytes with the spaces. Conversely, adding these 5 bytes to the 13 means growing the size of 38.46%. Anyway, you'll see later on why the size matters.</p>
<h2 id="heading-from-boring-to-warning">From boring, to warning</h2>
<p>I started to draw my chessboard pattern by hand happily, and within a few seconds, an intense feeling of boredom started to gain me as I was making plenty of errors and progressing very slowly. I didn't let it kill the idea. Instead, I did "File &gt; New &gt; Scratch File" in Android Studio (also works in IntelliJ IDEA), selected Kotlin, and started leveraging software to do this cumbersome task. Within 2 minutes, I wrote 2 <code>for</code> loops in a <code>buildString { … }</code>, and it seemed to generate what I was looking for. I copied it in the <code>pathData</code> of the VectorDrawable I had started writing by hand, and after 1 or 2 fixes, plus a size change, it was showing exactly what I wanted… and an extra thing, a warning from the IDE.</p>
<blockquote>
<p>Very long vector path (1504 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector.</p>
</blockquote>
<p><em>(yes, it should be "Consider", without "ing)</em></p>
<p>I understood this could affect the device performance when it would draw the icon, something I definitely don't want to cause.</p>
<p>Here's the initial code that I had written for boxes of size 2:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateChessboardPattern1</span><span class="hljs-params">(size: <span class="hljs-type">Int</span>)</span></span>: String = buildString {
    <span class="hljs-keyword">for</span> (x <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until size step <span class="hljs-number">2</span>) {
        <span class="hljs-keyword">for</span> (y <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until size step <span class="hljs-number">2</span>) {
            <span class="hljs-keyword">if</span> ((x - y) % <span class="hljs-number">4</span> != <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>
            append(<span class="hljs-string">"M<span class="hljs-variable">$x</span>,<span class="hljs-subst">${y}</span>H<span class="hljs-subst">${x + <span class="hljs-number">2</span>}</span>V<span class="hljs-subst">${y + <span class="hljs-number">2</span>}</span>H<span class="hljs-subst">${x}</span>z"</span>)
        }
    }
}
</code></pre>
<p>As you can see, for every box that needs to be drawn, it adds something like that: <code>Mx,yHaVbHcz</code>. That is at least 11 characters per box, and on a 14x14 grid (28x28 with boxes of 2x2 technically), it quickly grew beyond the kilobyte worth of vector drawing instructions.</p>
<p>I didn't want to go raster, and I wanted to keep the same grid size, so I looked for ways I could end up with the same result while having less instructions.</p>
<h2 id="heading-iterating-on-optimizations">Iterating on optimizations</h2>
<h3 id="heading-minimizing-the-move-commands">Minimizing the move commands</h3>
<p>In the previous approach, the move command (<code>Mx,y</code>) accounted for 4 characters, or about a third of the entire command, so my first thought was to reduce these calls. With the code just below, I now get only one every 2 lines instead of for every box to fill:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateChessboardPattern2</span><span class="hljs-params">(size: <span class="hljs-type">Int</span>)</span></span>: String = buildString {
    check(size % <span class="hljs-number">4</span> == <span class="hljs-number">0</span>) { <span class="hljs-string">"Size must be a multiple of 4"</span> }
    <span class="hljs-keyword">for</span> (y <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until size step <span class="hljs-number">4</span>) {
        append(<span class="hljs-string">"M0,<span class="hljs-variable">$y</span>"</span>)
        <span class="hljs-keyword">for</span> (x <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until size step <span class="hljs-number">4</span>) {
            append(<span class="hljs-string">'H'</span>); append(x + <span class="hljs-number">2</span>)
            append(<span class="hljs-string">'V'</span>); append(y + <span class="hljs-number">4</span>)
            append(<span class="hljs-string">'H'</span>); append(x + <span class="hljs-number">4</span>)
            append(<span class="hljs-string">'V'</span>); append(y)
        }
        append(<span class="hljs-string">'V'</span>); append(y + <span class="hljs-number">2</span>)
        append(<span class="hljs-string">'H'</span>); append(<span class="hljs-number">0</span>)
        append(<span class="hljs-string">'V'</span>); append(y)
        append(<span class="hljs-string">"z "</span>)
    }
}
</code></pre>
<p>Of course, it introduced a new restriction: the size now had to be a multiple of 4. That was fine for me as it would not be customer facing. However, I was thinking I could do better.</p>
<h3 id="heading-removing-the-move-commands-altogether">Removing the move commands altogether</h3>
<p>First, I asked myself: "Can I draw that chessboard with just a single path?"</p>
<p><em>During my experiments, I had found out that lowercase <code>h</code> and <code>v</code> commands were relative position variants, which made it much easier to experiment manually right in the XML.</em></p>
<p>I tried the simplest version that would answer my question.</p>
<p>This is the path data I got: <code>M0,0h2v4h2V2H0z</code>, and this is what I was seeing in the IDE:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657814834176/VSVCgOGAi.png" alt="manual test, 2 green squares in chessboard pattern on a 2x2 grid" /></p>
<p>Then, I wanted to see what would happen if I removed the leading <code>M0,0</code>. The preview didn't change a bit. I tried breaking the thing (successfully) and when I reverted the bad things I had just done: it was showing the right thing again. I just realized that any path would start at <code>0,0</code> by default, which is exactly where I need to start for my use case!</p>
<p>Here is the complete VectorDrawable if you want to try for yourself in an actual Android Studio project.</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="utf-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">vector</span> <span class="hljs-attr">xmlns:android</span>=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>
    <span class="hljs-attr">android:width</span>=<span class="hljs-string">"108dp"</span>
    <span class="hljs-attr">android:height</span>=<span class="hljs-string">"108dp"</span>
    <span class="hljs-attr">android:viewportWidth</span>=<span class="hljs-string">"4"</span>
    <span class="hljs-attr">android:viewportHeight</span>=<span class="hljs-string">"4"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
        <span class="hljs-attr">android:fillColor</span>=<span class="hljs-string">"#C0C0"</span>
        <span class="hljs-attr">android:pathData</span>=<span class="hljs-string">"h2v4h2V2H0z"</span>
        <span class="hljs-attr">android:strokeWidth</span>=<span class="hljs-string">"0.3"</span>
        <span class="hljs-attr">android:strokeColor</span>=<span class="hljs-string">"#0F0"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">vector</span>&gt;</span>
</code></pre>
<p>The 2x2 grid (or 4x4 here, technically) seemed like a special case, and I was wondering what would happen for the filling for the boxes that I wanted empty that would be surrounded by boxes I wanted filled. Would they be filled as well, or would they be empty as I wanted?</p>
<p>I continued manually, and step by step, I got the following path data: <code>h2v8h2V0h2v8h2 v-2H0v-2h8v-2H0z</code>, which was fortunately exactly the result I was looking for:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657845237825/4TyTn7dtQ.png" alt="manual test, green squares in chessboard pattern on a 4x4 grid" /></p>
<p>Then I went to write the code, and also designed the function so it was supporting a variable box size, and so it could evolve to support rectangle boards as well as rectangle boxes. <em>It's missing a few preconditions, for example to reject a <code>boxSize</code> that is greater than the <code>size</code>, but it's only run locally on my dev machine here, I don't see why I would try such a thing.</em></p>
<p>Instead of drawing the boxes one by one, or 2 lines by 2 lines with nested for loops, it draws the vertical lines, and then, draws the horizontal lines before closing the path.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657844187466/lskWiZIZV.png" alt="purple chessboard pattern" /></p>
<p>The previous implementation had a quadratic complexity, and the result had a size that would grow a lot with the grid size, while the one below has a linear complexity, with a result that grows only linearly with the size as well.</p>
<p>Here is the code:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-built_in">Int</span>.<span class="hljs-title">isOdd</span><span class="hljs-params">()</span></span> = <span class="hljs-keyword">this</span> % <span class="hljs-number">2</span> != <span class="hljs-number">0</span> <span class="hljs-comment">// It's odd that this isn't built into Kotlin, isn't it?</span>

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateChessboardPattern3</span><span class="hljs-params">(
    size: <span class="hljs-type">Int</span>,
    boxSize: <span class="hljs-type">Int</span>
)</span></span>: String = buildString {
    <span class="hljs-keyword">val</span> boxWidth = boxSize
    <span class="hljs-keyword">val</span> boxHeight = boxSize
    <span class="hljs-keyword">val</span> width = size
    <span class="hljs-keyword">val</span> height = size
    <span class="hljs-keyword">for</span> (x <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until width step boxWidth) {
        append(<span class="hljs-string">"h<span class="hljs-subst">${boxWidth}</span>"</span>)
        <span class="hljs-keyword">if</span> (x + boxWidth == width) <span class="hljs-keyword">break</span> <span class="hljs-comment">// Don't draw the last line.</span>
        <span class="hljs-keyword">val</span> verticalOffset = <span class="hljs-keyword">if</span> ((x / boxWidth).isOdd()) <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> height
        append(<span class="hljs-string">'V'</span>)
        append(verticalOffset)
    }
    <span class="hljs-keyword">for</span> (y <span class="hljs-keyword">in</span> height downTo  <span class="hljs-number">0</span> step boxHeight) {
        append(<span class="hljs-string">"v-<span class="hljs-subst">${boxHeight}</span>"</span>)
        <span class="hljs-keyword">if</span> (y - boxHeight == <span class="hljs-number">0</span>) <span class="hljs-keyword">break</span> <span class="hljs-comment">// Don't draw the last line.</span>
        <span class="hljs-keyword">val</span> horizontalOffset = <span class="hljs-keyword">if</span> ((y / boxHeight).isOdd()) height <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>
        append(<span class="hljs-string">'H'</span>)
        append(horizontalOffset)
    }
    append(<span class="hljs-string">'z'</span>)
}
</code></pre>
<h3 id="heading-the-last-tiny-optimization">The last tiny optimization</h3>
<p>Before I had even started writing the 3rd version above, I was thinking that the potentially equivalent <code>v-2</code> was longer than <code>V8</code>, but at the same time, <code>v-2</code> is shorter than <code>V10</code>. I didn't let this stop me from writing a simple working version first, but then, I changed 3 lines in the second for loop for the 4th iteration, allowing me to shave a few extra bytes in the result where possible:</p>
<pre><code class="lang-kotlin"><span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">generateChessboardPattern4</span><span class="hljs-params">(
    size: <span class="hljs-type">Int</span>,
    boxSize: <span class="hljs-type">Int</span>
)</span></span>: String = buildString {
    <span class="hljs-keyword">val</span> boxWidth = boxSize
    <span class="hljs-keyword">val</span> boxHeight = boxSize
    <span class="hljs-keyword">val</span> width = size
    <span class="hljs-keyword">val</span> height = size
    <span class="hljs-keyword">for</span> (x <span class="hljs-keyword">in</span> <span class="hljs-number">0</span> until width step boxWidth) {
        append(<span class="hljs-string">"h<span class="hljs-subst">${boxWidth}</span>"</span>)
        <span class="hljs-keyword">if</span> (x + boxWidth == width) <span class="hljs-keyword">break</span> <span class="hljs-comment">// Don't draw the last line.</span>
        <span class="hljs-keyword">val</span> verticalOffset = <span class="hljs-keyword">if</span> ((x / boxWidth).isOdd()) <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> height
        append(<span class="hljs-string">'V'</span>)
        append(verticalOffset)
    }
    <span class="hljs-keyword">for</span> (y <span class="hljs-keyword">in</span> height downTo  <span class="hljs-number">0</span> step boxHeight) {
        <span class="hljs-keyword">val</span> targetY = y - boxHeight <span class="hljs-comment">// &lt;- changed</span>
        append(<span class="hljs-keyword">if</span> (targetY &gt;= <span class="hljs-number">10</span>) <span class="hljs-string">"v-<span class="hljs-subst">${boxHeight}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">"V<span class="hljs-subst">${targetY}</span>"</span>) <span class="hljs-comment">// &lt;- changed</span>
        <span class="hljs-keyword">if</span> (targetY == <span class="hljs-number">0</span>) <span class="hljs-keyword">break</span> <span class="hljs-comment">// Don't draw the last line. // &lt;- changed</span>
        <span class="hljs-keyword">val</span> horizontalOffset = <span class="hljs-keyword">if</span> ((y / boxHeight).isOdd()) height <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>
        append(<span class="hljs-string">'H'</span>)
        append(horizontalOffset)
    }
    append(<span class="hljs-string">'z'</span>)
}
</code></pre>
<p>With the following code:</p>
<pre><code class="lang-kotlin">println(<span class="hljs-string">"approach number 3:"</span>)
println(generateChessboardPattern3(size = <span class="hljs-number">28</span>, boxSize = <span class="hljs-number">2</span>))
println(<span class="hljs-string">"approach number 4:"</span>)
println(generateChessboardPattern4(size = <span class="hljs-number">28</span>, boxSize = <span class="hljs-number">2</span>))
</code></pre>
<p>I checked how they compared:</p>
<pre><code class="lang-txt">approach number 3:
h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2z
approach number 4:
h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2V0h2V28h2v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0v-2H28v-2H0V8H28V6H0V4H28V2H0V0z
</code></pre>
<p>With just 5 characters saved, clearly, we're seeing the effects of <a target="_blank" href="https://en.wikipedia.org/wiki/Diminishing_returns">the law of diminishing returns</a>, but I still took it. Time has already been spent on it, no significant downside… ¯_(ツ)_/¯</p>
<p>The last two possible optimizations (that I didn't check if <a target="_blank" href="https://developer.android.com/studio/command-line/aapt2">aapt2</a> was doing) are renaming the <code>android</code> xml namespace to <code>a</code>, and removing all the non mandatory spaces and line breaks. Anyway, I saved 81 bytes there (more than 20% less compared to the previous iteration).</p>
<h2 id="heading-counting-the-savings">Counting the savings</h2>
<p>That was quite a journey! To be honest, it was very quick on my end, but writing the article made it much longer… 😅 Sharing is caring!</p>
<p>If you take the entire file size, we started at 1812 bytes, and the most optimized version is now 318 bytes, which <strong>5.7x smaller</strong>!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657845838027/oLbBTKjDn.png" alt="screenshot showing the file sizes decrease after each iteration" /></p>
<p>If you take just the path data, we started from 1504 bytes/chars down to 131 bytes/chars, or <strong>11.4x smaller</strong>!</p>
<h2 id="heading-bonus-1-how-to-draw-lines-that-are-neither-horizontal-neither-vertical">Bonus 1: How to draw lines that are neither horizontal, neither vertical?</h2>
<p>It's very easy, just like we've been doing <code>Mx,y</code> to move to a position in the beginning, use <code>Lx,y</code>, and it'll draw a line to the given absolute position, or use the lowercase variant for a relative position (<code>lx,y</code>).
Now I want to learn how to draw curves… maybe later.</p>
<h2 id="heading-bonus-2-how-to-convert-a-vectordrawable-to-a-pixel-perfect-png">Bonus 2: How to convert a VectorDrawable to a pixel-perfect PNG?</h2>
<p>For this article, I've been looking for a way to get a png out of my VectorDrawables.</p>
<p>I first failed to find a proper way to do it, so I was using screenshots and cropped roughly.
Then I failed at finding a working tool to convert them to SVG before I could extract a PNG.
I then successfully did the conversion by hand, where I happily learned a bit more about SVG.
Then some folks in the community pointed me to <code>VdPreview.getPreviewFromVectorXml()</code>, located in <a target="_blank" href="https://maven.google.com/web/index.html#com.android.tools:sdk-common">com.android.tools:sdk-common</a>, a dependency of AGP (the Android Gradle Plugin).
So, I added the dependency, and with the following code, I can now get a nice PNG file from any Android VectorDrawable:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> com.android.ide.common.vectordrawable.VdPreview
<span class="hljs-keyword">import</span> java.io.File
<span class="hljs-keyword">import</span> javax.imageio.ImageIO

<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">saveImageFromVectorDrawableAndReturnErrors</span><span class="hljs-params">(
    xml: <span class="hljs-type">String</span>,
    maxDimension: <span class="hljs-type">Int</span>,
    outputFile: <span class="hljs-type">File</span>
)</span></span>: String? {
    <span class="hljs-keyword">val</span> errors = StringBuilder()
    <span class="hljs-keyword">val</span> bufferedImage = VdPreview.getPreviewFromVectorXml(
        VdPreview.TargetSize.createFromMaxDimension(maxDimension),
        xml,
        errors
    )
    ImageIO.write(bufferedImage, <span class="hljs-string">"png"</span>, outputFile)
    <span class="hljs-keyword">return</span> errors.takeIf { it.isNotEmpty() }?.toString()
}
</code></pre>
<p>It'd probably be worth wrapping that in a CLI tool, it's very easy to do with Kotlin scripts since they support dependencies.</p>
<hr />
<p>To wrap it up, here's a chessboard sized grid drawn with the generated code I've been showing you. And about the cover picture, the Kotlin logos with chessboard/checkerboard patterns are self-made, I got to learn a bit about SVG as well, which uses the exact same format for pathData (but requires an initial move instruction [<code>Mx,y</code>]).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1657844329934/HuV40Uy_V.png" alt="chessboard pattern, 8x8, like an actual chessboard" /></p>
<p>Of course, you can copy the code above 100% freely, no mention needed.</p>
<p>If you enjoyed this article or found it useful, which I hope so, please add a thumbs up or something, you can very easily connect with a GitHub, Google, Apple, or even a LinkedIn account! (email also works). 🙏
You can also click the subscribe button on this page to see my future dev blog posts, or/and you can <a target="_blank" href="https://twitter.com/Louis_CAD">follow me on Twitter</a>.</p>
<p>Have a great day!</p>
]]></content:encoded></item><item><title><![CDATA[Coroutines racing! Why, and how.]]></title><description><![CDATA[Over the years, I found myself needing the following:
Run multiple related coroutines (i.e. asynchronous operations), and when one completes, cancel/stop the other ones.
As usual, and especially since we're in Kotlin, I have been looking for the easi...]]></description><link>https://blog.louiscad.com/coroutines-racing-why-and-how</link><guid isPermaLink="true">https://blog.louiscad.com/coroutines-racing-why-and-how</guid><category><![CDATA[Kotlin]]></category><category><![CDATA[coroutines]]></category><category><![CDATA[concurrency]]></category><dc:creator><![CDATA[Louis CAD]]></dc:creator><pubDate>Mon, 08 Nov 2021 07:52:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636438814942/F2vcURtqW.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Over the years, I found myself needing the following:</p>
<p>Run multiple related coroutines (i.e. asynchronous operations), and when one completes, cancel/stop the other ones.</p>
<p>As usual, and especially since we're in Kotlin, I have been looking for the easiest way to do it correctly, and efficiently.</p>
<p>Within the kotlinx.coroutines first party library, I didn't find the high-level API I was looking for, though the building blocks to make it were definitely there.</p>
<p>Before we look at the solution I've been using, let's see some use cases for coroutines racing.</p>
<h2 id="why-race-in-the-first-place">Why race in the first place</h2>
<p>The kind of use case that I found to be the most obvious is allowing triggering something via multiple means. For example, we could have a manual and an automatic way of enabling something. Or we could have a local and remote way of turning off something else. Or, more simply, we could have two buttons that do the same thing. Maybe you can think of one or two other plausible scenarios fitting this kind of use case.</p>
<p>Another kind of use case is having multiple terminal operations. For example, during an onboarding step in an app, or an app feature, we could expect the user to request watching a quick video introduction, while being able to skip it midway.</p>
<p>There are of course many other reasons we would want to race coroutines.</p>
<p>Before moving on to the how, I want to emphasize the desired behavior: when one of the racing coroutines completes, we want all other race contenders to be cancelled.</p>
<h2 id="our-example-use-case">Our example use case</h2>
<p>For the rest of this article, and for the sake of simplicity, we'll settle on the triggering use case.</p>
<p>A triggering operation can be abstracted away as a suspending function with such a signature:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">awaitTrigger</span><span class="hljs-params">()</span></span>
</code></pre>
<p>As you can guess, we would expect that function to return/resume when it's time to trigger the thing.</p>
<p>Now, for the multiple trigger means, we could imagine that we actually have two other suspending functions: <code>awaitAutomaticTrigger()</code>, and <code>awaitManualTrigger()</code>.</p>
<p>How can we race these two functions?</p>
<h2 id="a-basic-approach">A basic approach</h2>
<p>If you want to race two coroutines, here's one way you could come up with:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">awaitTrigger</span><span class="hljs-params">()</span></span> {
    coroutineScope {
        <span class="hljs-keyword">val</span> automaticTrigger = launch {
            awaitAutomaticTrigger()
            <span class="hljs-comment">// Aaargh, can't access `manualTrigger` here!</span>
        }
        <span class="hljs-keyword">val</span> manualTrigger = launch {
            awaitManualTrigger()
            automaticTrigger.cancel()
        }
        <span class="hljs-comment">// `coroutineScope { … }` suspends until all children are complete or cancelled,</span>
        <span class="hljs-comment">// so no need to call `join()`, nor go with an extra indirection.</span>
    }
}
</code></pre>
<p>As you can see, the most straightforward approach, that works for just two racers, already has a shortcoming (as you can see in the "Aaargh" comment). One workaround is declaring <code>manualTrigger</code> as a <code>lateinit var</code>. Works, but not so neat, and it's now underlined by our IDE 😔.</p>
<h2 id="what-would-be-an-ideal-api">What would be an ideal API?</h2>
<p>Well, we can never really know what the absolute best API could be, but let's at least imagine something easier to use than the previous snippet that would serve the same purpose.</p>
<p>That API would need to surface the intent of racing multiple suspend calls, with the cancelling behavior for the non-winners.</p>
<p>So, it'd need the verb "race" in its name, and it'd need to take multiple suspending functions as a parameter?
How could it look for our triggering use case?</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> awaitTrigger() = raceOf({
    awaitAutomaticTrigger()
}, {
    awaitManualTrigger()
})
</code></pre>
<p>So, we went from 11 lines of code, including 8 significant, to 5 lines of code, including 3 significant. Quite cool?</p>
<p>If you analyze the two snippets, you'll also see that for the first approach, unless we rework it, the number of lines of code, <em>and the potential mistakes one can make along the way</em>, grows exponentially as we add more racers, while for this <code>raceOf</code> API, it grows linearly at a rate of only 2 lines of code per racer, with a single one significant.</p>
<p>That API, while very simple, has one shortcoming: the number of racing coroutines is fixed at compile time, just like all <code>vararg</code> parameters, which is what <code>raceOf</code> takes. It's possible to use the spread operator after converting a list of suspend functions to a typed array, but it's not optimal, and it doesn't allow late racers.</p>
<p>To support a dynamic amount of coroutines, and late racers, we can imagine another API. A <code>race { … }</code> function would bring a <code>RacingScope</code> where you could call <code>launchRacer { … }</code> inside to, well, launch racers.</p>
<p>Here's how it'd look for the triggering use case:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> awaitTrigger() = race {
    launchRacer { awaitAutomaticTrigger() }
    launchRacer { awaitManualTrigger() }
}
</code></pre>
<p>Interestingly, it's even less code than our previous approach, and each additional racer can take as little as 1 line of code in total.</p>
<h2 id="how-could-that-coroutines-racing-api-be-implemented">How could that coroutines racing API be implemented?</h2>
<p>The first time I wanted to race coroutines with a neat API was about 3 years ago. I also wanted it to support returning the value of the winning racer/coroutine.</p>
<p>My first idea was to make a suspending extension function on <code>List&lt;Deferred&gt;</code> that I named <code>race</code>, and I implemented it with one <code>CompletableDeferred</code> instance and a loop:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> List<span class="hljs-type">&lt;Deferred&lt;T&gt;</span>&gt;.<span class="hljs-title">race</span><span class="hljs-params">()</span></span>: T = coroutineScope {
    <span class="hljs-keyword">val</span> winningValue = CompletableDeferred&lt;T&gt;()
    <span class="hljs-keyword">this</span><span class="hljs-symbol">@race</span>.forEach { racer -&gt;
        launch {
            <span class="hljs-keyword">val</span> winningCandidate = racer.await()
            <span class="hljs-keyword">this</span><span class="hljs-symbol">@race</span>.forEach { <span class="hljs-keyword">if</span> (it != racer) it.cancel() }
            winningValue.complete(winningCandidate)
        }
    }
    winningValue.await()
}
</code></pre>
<p>I then found it inconvenient to have to create the <code>Deferred</code> instances via calls to <code>async { … }</code> that had to be done inside of another <code>coroutineScope { … }</code> block, so I put that boilerplate inside a function named <code>raceOf</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">race</span><span class="hljs-params">(<span class="hljs-keyword">vararg</span> racers: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>)</span></span>: T = coroutineScope {
    <span class="hljs-keyword">val</span> list: List&lt;Deferred&lt;T&gt;&gt; = racers.map { racer -&gt; async { racer() } }
    <span class="hljs-keyword">val</span> winningValue = CompletableDeferred&lt;T&gt;()
    list.forEach { racer -&gt;
        launch {
            <span class="hljs-keyword">val</span> winningCandidate = racer.await()
            list.forEach { racer.cancel() } <span class="hljs-comment">// Cancelling a complete Job is no-op.</span>
            winningValue.complete(winningCandidate)
        }
    }
    winningValue.await()
}
</code></pre>
<p>Thanks to the help of folks on Kotlin's Slack and some searching, I then found that I could also use the <code>select</code> clause for that:</p>
<pre><code class="lang-kotlin"><span class="hljs-comment">/**
 * Races all the [racers] concurrently. Once the winner completes, all other racers are cancelled,
 * then the value of the winner is returned.
 */</span>
<span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-type">&lt;T&gt;</span> <span class="hljs-title">raceOf</span><span class="hljs-params">(<span class="hljs-keyword">vararg</span> racers: <span class="hljs-type">suspend</span> <span class="hljs-type">CoroutineScope</span>.() -&gt; <span class="hljs-type">T</span>)</span></span>: T = coroutineScope {
    select&lt;T&gt; {
        <span class="hljs-keyword">val</span> racersAsyncList = racers.map { async(start = CoroutineStart.UNDISPATCHED, block = it) }
        racersAsyncList.forEachByIndex { racer: Deferred&lt;T&gt; -&gt;
            racer.onAwait { resultOfWinner: T -&gt;
                racersAsyncList.forEachByIndex { deferred: Deferred&lt;T&gt; -&gt; deferred.cancel() }
                <span class="hljs-keyword">return</span><span class="hljs-symbol">@onAwait</span> resultOfWinner
            }
        }
    }
}
</code></pre>
<p>Both implementations work fine.</p>
<p>It's very possible one is more performant than the other. I didn't benchmark because I am not putting these implementations under a high stress (<em>i.e.</em> high number of racers, or calling them at a high frequency), and they have never been the cause of any performance or stability issue. If you have such a demanding use case, feel free to do the benchmark and your testing approach, and share/link it in the comments below, I'll be interested in seeing it! I'd bet the <code>select</code> based implementation is the most efficient, but I wouldn't put much on table for that mostly intuition-based guess.</p>
<h2 id="sharing-that-work-widely">Sharing that work widely</h2>
<p>Since I thought I might not be the only one with this use case, I put the <code>select</code> based implementation of <code>raceOf</code> into one of the <a target="_blank" href="https://github.com/LouisCAD/Splitties/">Splitties</a> libraries, and that Kotlin multiplatform library also includes the <code>race</code> function for dynamic number of racers that I was referring to earlier in this article (permalink to its implementation <a target="_blank" href="https://github.com/LouisCAD/Splitties/blob/1ea7e072ae7fba5b989f226dd8371cd22d0916ed/modules/coroutines/src/commonMain/kotlin/splitties/coroutines/Racing.kt#L82-L133">here</a>).</p>
<p>You can find the host library module <a target="_blank" href="https://github.com/LouisCAD/Splitties/tree/main/modules/coroutines">here</a>, with the entire source code, the documentation, and setup info to add the library to your project.</p>
<p>However, having this in a third-party library limits the accessibility of these coroutines racing facilities which I believe could be useful in many Kotlin projects. That's why I submitted <a target="_blank" href="https://github.com/Kotlin/kotlinx.coroutines/issues/2867">an issue in the kotlinx.coroutines GitHub repository</a> to ask for that use case to be addressed in the first-party library from the Kotlin team. Feel free to add a 👍 reaction to it so the priority gets high enough for it to be considered before we are all dead!</p>
<p>I hope you enjoyed reading and learned something helpful. Have a great Kotlin… well, have a great everything!</p>
]]></content:encoded></item><item><title><![CDATA[How to return 2+ values with 0 allocation in Kotlin]]></title><description><![CDATA[The problem
Most programming languages, including Kotlin, only allow returning one value, and there's a reason for that: We don't want to depend solely on the order of the parameters, because it can easily break through refactoring, or even before th...]]></description><link>https://blog.louiscad.com/how-to-return-2-values-with-0-allocation-in-kotlin</link><guid isPermaLink="true">https://blog.louiscad.com/how-to-return-2-values-with-0-allocation-in-kotlin</guid><category><![CDATA[Kotlin]]></category><dc:creator><![CDATA[Louis CAD]]></dc:creator><pubDate>Mon, 20 Sep 2021 11:29:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632137032938/56weTvVnK.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="the-problem">The problem</h2>
<p>Most programming languages, including Kotlin, only allow returning one value, and there's a reason for that: We don't want to depend solely on the order of the parameters, because it can easily break through refactoring, or even before that.</p>
<p>When we want to return multiple things, we put it into a container: a class.
However, that approach has 2 caveats:</p>
<ol>
<li>Requires extra allocation</li>
<li>Requires naming the class</li>
</ol>
<p>If the code is not called at high frequency (many times per second), and not in UI, the first caveat should not be a concern.</p>
<p>However, the second caveat means that in addition to naming the function and the multiple things you are returning, <strong>you need to name that extra class</strong>. This is <strong>extra burden</strong>, and in some cases, it might lead you to give quite uninspiring names like <code>Thing1AndThing2WithDetail3</code>, making the code slightly more complex.</p>
<p>What if I told you that in Kotlin, it's possible to get more than one value out of a function execution, without any allocation, and with no class to name?</p>
<h2 id="the-solution">The solution</h2>
<p>Since Kotlin 1.3, the code below can compile.</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">val</span> theBonus: Bonus
<span class="hljs-keyword">val</span> theStuff = getStuff { theBonus = it }

doSomething(theStuff, theBonus)
</code></pre>
<p>Maybe you know the saying that Kotlin's best feature is how all of its features can work together so smoothly?</p>
<p>Well, here we are using the following Kotlin features together:</p>
<ul>
<li>inline functions/lambdas</li>
<li>read-only properties (aka. val)</li>
<li>contracts</li>
</ul>
<p>The <code>getStuff</code> inline function has a contract that promises to the compiler that given it executes without throwing, the lambda it has been passed will always have been called exactly once upon returning.</p>
<p>Thanks to that contract, the compiler allows the read-only property <code>theBonus</code> to be initialized from this lambda, and considers it as initialized after the <code>getStuff</code> call.</p>
<p>The <code>getStuff</code> function is defined like that:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> kotlin.contracts.*

<span class="hljs-meta">@OptIn(ExperimentalContracts::class)</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getStuff</span><span class="hljs-params">(block: (<span class="hljs-type">Bonus</span>) -&gt; <span class="hljs-type">Unit</span>)</span></span>: Stuff {
    contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
    <span class="hljs-keyword">val</span> stuff = grabStuffFromCargoBikeBasket()
    <span class="hljs-keyword">val</span> bonus = inspirationElixir()
    block(bonus)
    <span class="hljs-keyword">return</span> stuff
}
</code></pre>
<p>Here, there's no extra allocation, and no need to name the class. However, you need to name the lambda in the <code>getStuff</code> signature, but <code>block</code> or <code>action</code> is often sufficient for these trailing lambda use cases, so it shouldn't "drain" or consume your creativity.</p>
<p>There's one potential caveat though, and it pertains to the inline nature of the function. As you might know, a function being inlined means that the compiler will basically copy the compiled code at each call-site. That's perfectly fine if the amount of inline code is very little, or quite limited, but if that's a giant function that possibly also calls other inline functions that are potentially substantial as well… it can make the compiled binary grow significantly, which in addition to taking up extra storage for your users, and bandwidth on download, can also make loading the program from a cold-start longer, and increase memory (RAM) consumption. All of this doesn't go in the direction go towards a better UX. That should not be a concern if you are not inlining long algorithms or so long as you stay under a dozen of function calls though. If you're in a such a case and are unsure about the impact, make your own tests to measure the relative impact in context.</p>
<p><em>By the way, you might have noticed that we had to opt-in to "ExperimentalContracts". This is because the syntax to define contracts in Kotlin might/will change in the future, which mean you'll likely need to migrate the code (hopefully with full IDE-assistance to do it in one click). However, publishing functions that use contracts is perfectly fine, even in a public library, because compiled contracts are already stable since Kotlin 1.3, so for example, users on Kotlin 1.7 will still be able to use contracts from a library compiled with Kotlin 1.3.</em></p>
<h2 id="an-actual-use-case">An actual use-case</h2>
<p>For those that like small stories, I want to share the use-case I had where I came up with this trick.</p>
<p>As I was testing stuff around Wi-Fi connectivity on Android, I wanted to see the signal strength on the system scale (which is often 0 to 4 bars). For historical reasons, there are 2 APIs to do that on Android, one that works on recent versions, and a deprecated one that works on older versions. As usual, I added a <code>when</code> or an <code>if</code>/<code>else</code> expression. However, the APIs has a tricky difference:</p>
<ul>
<li>On older Android versions, you pass the scale: I'd pass 4 or 5.</li>
<li>On newer Android versions, you get the scale from the system API, which is dynamic, not much assumptions can be made.</li>
</ul>
<p>To display the correct signal strength, I'd need two values: the scale, and the max level, which would default to whatever desired on older Android versions.</p>
<p>Sure, I could have used a <code>Double</code> or a <code>Float</code>, but I like my numbers whole when possible, especially when the scale is small, which is the case here.</p>
<p>So the <code>calculateSignalLevel</code> extension function for <code>WifiInfo</code> would take the <code>fallbackNumLevels</code> parameter for older Android versions (defaulting to 5, per my arbitrary choice), the <code>getNumLevels</code> lambda to feed the actual scale, and would return the signal strength on that scale.</p>
<p>Here's how the function looks like:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">import</span> android.net.wifi.WifiInfo
<span class="hljs-keyword">import</span> android.net.wifi.WifiManager
<span class="hljs-keyword">import</span> android.os.Build
<span class="hljs-keyword">import</span> splitties.systemservices.wifiManager
<span class="hljs-keyword">import</span> kotlin.contracts.ExperimentalContracts
<span class="hljs-keyword">import</span> kotlin.contracts.InvocationKind
<span class="hljs-keyword">import</span> kotlin.contracts.contract

<span class="hljs-meta">@OptIn(ExperimentalContracts::class)</span>
<span class="hljs-keyword">inline</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> WifiInfo.<span class="hljs-title">calculateSignalLevel</span><span class="hljs-params">(
    fallbackNumLevels: <span class="hljs-type">Int</span> = <span class="hljs-number">5</span>,
    getNumLevels: (<span class="hljs-type">numLevels</span>: <span class="hljs-type">Int</span>) -&gt; <span class="hljs-type">Unit</span>
)</span></span>: <span class="hljs-built_in">Int</span> {
    contract { callsInPlace(getNumLevels, InvocationKind.EXACTLY_ONCE) }
    <span class="hljs-keyword">val</span> wifiManager = checkNotNull(wifiManager) { <span class="hljs-string">"Wi-Fi info is not supported in instant apps"</span> }
    <span class="hljs-keyword">val</span> actualNumLevels = <span class="hljs-keyword">when</span> {
        Build.VERSION.SDK_INT &gt;= <span class="hljs-number">30</span> -&gt; wifiManager.maxSignalLevel
        <span class="hljs-keyword">else</span> -&gt; fallbackNumLevels
    }
    getNumLevels(actualNumLevels)
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">when</span> {
        Build.VERSION.SDK_INT &gt;= <span class="hljs-number">30</span> -&gt; wifiManager.calculateSignalLevel(rssi)
        <span class="hljs-keyword">else</span> -&gt; <span class="hljs-meta">@Suppress(<span class="hljs-meta-string">"deprecation"</span>)</span> WifiManager.calculateSignalLevel(rssi, actualNumLevels)
    }
}
</code></pre>
<p>The <code>wifiManager</code> top-level property comes from the <a target="_blank" href="https://splitties.louiscad.com/modules/systemservices/">Splitties System Services</a> library that saves the tiny boilerplate otherwise needed. After all, why accept unneeded boilerplate when it can even be inlined to be like hand-written?</p>
<hr />
<p>That's it!
I hope you learned something.
Personally, I'm happy to finish my first blog post after almost 7 years developing Android apps full-time (overtime?), and 5 years of Kotlin 😅.</p>
<p>Have a great day, and see you in my next blog posts (you can click the subscribe button if you wish), <a target="_blank" href="https://twitter.com/Louis_CAD">on Twitter</a>, and maybe even on Kotlin Slack!</p>
]]></content:encoded></item></channel></rss>