# Posts on Romain Guy

Recent content in Posts on Romain Guy

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## Weekly recommendations of articles and videos about programming, graphics, and computing

DevFeed: [Weekly recommendations of articles and videos about programming, graphics, and computing](<https://devfeed.tech/articles/things-3-25615.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2026/things-3/>)

Author: Romain Guy

Published: 2026-08-20T00:00:00Z

Content type: article

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Programming](<https://devfeed.tech/topics/programming.md>), [GPU](<https://devfeed.tech/topics/gpu.md>), [intel](<https://devfeed.tech/topics/intel.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [article](<https://devfeed.tech/tags/article.md>), [articles](<https://devfeed.tech/tags/articles.md>), [books](<https://devfeed.tech/tags/books.md>), [developer](<https://devfeed.tech/tags/developer.md>), [fpu](<https://devfeed.tech/tags/fpu.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [intel](<https://devfeed.tech/tags/intel.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [links](<https://devfeed.tech/tags/links.md>), [precision](<https://devfeed.tech/tags/precision.md>), [programming](<https://devfeed.tech/tags/programming.md>), [videos](<https://devfeed.tech/tags/videos.md>)

### AI overview

A weekly roundup of recommended reading and viewing covering Intel's MMX, linear algebra, floating-point precision, Bézier curves, blackbody color fits, GPU memory behavior, and Game Boy Advance graphics modes.

### Source excerpt

Here is a list of tings I read/watched/played/etc. this week that you might find interesting or enjoyable: Things to read Link to heading SIMD in the 90s -- Great article explaining what Intel's MMX was all about. Linear algebra done right -- Contains a lot of stuff that I feel like I have to relearn every few years. Double-double: 31 digits of precision without leaving the FPU -- I really, really like reading about floaing points :) Curvature Béziers -- Yet another fascinating article on Bézier curves, this time with a focus on curvature. Blackbody: 4 rational fits -- A set of analytical fits for blackbody colors, from 798 to 5772 K. I have used a common fit before, but these fits look more useful in some situations. What happens when a GPU reads memory -- More information about how GPUs work is always welcome. Things to watch Link to heading How the Game Boy Advance's graphics modes made it so advanced -- A tour of the GameBoy Advance's graphics modes. I had a blast programming for the GBA back then, I kind of miss this style of graphics programming.

## Weekly recommendations for reading, watching, and trying

DevFeed: [Weekly recommendations for reading, watching, and trying](<https://devfeed.tech/articles/things-1-25613.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2026/things-1/>)

Author: Romain Guy

Published: 2026-08-06T00:00:00Z

Content type: opinion

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [C++](<https://devfeed.tech/topics/c-plus-plus.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>), [benchmarking](<https://devfeed.tech/topics/benchmarking.md>), [GPU](<https://devfeed.tech/topics/gpu.md>), [render](<https://devfeed.tech/topics/render.md>), [Open Source](<https://devfeed.tech/topics/open-source.md>), [Cloud](<https://devfeed.tech/topics/cloud.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [articles](<https://devfeed.tech/tags/articles.md>), [benchmarking](<https://devfeed.tech/tags/benchmarking.md>), [books](<https://devfeed.tech/tags/books.md>), [c-plus-plus](<https://devfeed.tech/tags/c-plus-plus.md>), [cloud](<https://devfeed.tech/tags/cloud.md>), [developer](<https://devfeed.tech/tags/developer.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [links](<https://devfeed.tech/tags/links.md>), [open-source](<https://devfeed.tech/tags/open-source.md>), [render](<https://devfeed.tech/tags/render.md>), [videos](<https://devfeed.tech/tags/videos.md>)

### AI overview

A weekly list of recommendations covering C++26 std::hive internals and performance, rendering and GPU techniques, animation, mountaineering, films, an open-source cloud computer, and parallel Delaunay triangulation.

### Source excerpt

Here is a list of tings I read/watched/played/etc. this week that you might find interesting or enjoyable: Things to read Link to heading A Deep Dive into C++26 std::hive: The Ultimate Container for Active Data -- Some details about the internals of C++ 26's new data structure. How fast is C++26's std::hive? -- Pretty self-explanatory and useful numbers to keep in mind. A Spectral BSSRDF for Shading Human Skin -- A spectral shading model that can be used to render different skin tones. On the Accuracy of Surface Scattering Theories -- Another reason why our rendering models are not quite good enough. A Texture Lookup Approach to Bézier Curve Evaluation on the GPU -- A clever use of GPU textures units to render Bézier curves efficiently. Haikyu!! -- I've been re-reading this manga. The anime is also worth it, for the animation itself. Annapurna: First Conquest of an 8000-meter Peak -- Maurice Herzog's account of the first successful ascent of Annapurna. Read the French original if you can. And you might want to read True Summit afterwards. Things to watch Link to heading Benchmarking - It's About Time -- Benchmarking is hard, but Matt Godbolt makes it fun and interesting. Nirvanna the Band the Show the Movie -- I watched it without knowing what it was really about. You should do the same, it takes an unexpected turn. Things I want to try Link to heading Wasmo -- An Open Source "cloud computer". delaunay32 -- Fast, parallel 2D Delaunay triangulation using exact integer predicates.

## Tap Detection on Arbitrary Shapes with Compose

DevFeed: [Tap Detection on Arbitrary Shapes with Compose](<https://devfeed.tech/articles/tap-detection-on-arbitrary-shapes-with-compose-25609.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2025/arbitrary-shape-tap-detection/>)

Author: Romain Guy

Published: 2025-12-07T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Android](<https://devfeed.tech/topics/android.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [api](<https://devfeed.tech/tags/api.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [image](<https://devfeed.tech/tags/image.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [parameter](<https://devfeed.tech/tags/parameter.md>), [performance](<https://devfeed.tech/tags/performance.md>), [pixel](<https://devfeed.tech/tags/pixel.md>), [render](<https://devfeed.tech/tags/render.md>)

### AI overview

This tutorial explains how to use Jetpack Compose's PathHitTester API to detect taps and test whether 2D coordinates lie inside arbitrary paths. It covers coordinate transformations, efficient repeated hit testing, updating the tester after path changes, and generating paths from images with the pathway library.

### Source excerpt

Detecting whether a user tapped on an arbitrary shape represented by a Path is an unfortunately difficult task on Android. The Path class does not offer any API to do this, and the workaround I have seen folks use (representing the tap as a small rectangle/circle and computing the intersection with the test shape) is inefficient and sometimes fails. Thankfully, Jetpack Compose a simple way to perform this task. The video below shows how the Compose APIs can be used to detect taps, or generally perform any test requiring to check whether a specific 2D coordinate is contained inside a Path:

## Finger Shadows in Compose

DevFeed: [Finger Shadows in Compose](<https://devfeed.tech/articles/finger-shadows-in-compose-25611.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2025/finger-shadows/>)

Author: Romain Guy

Published: 2025-11-29T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Compose](<https://devfeed.tech/topics/compose.md>), [Android](<https://devfeed.tech/topics/android.md>), [GPU](<https://devfeed.tech/topics/gpu.md>), [shaders](<https://devfeed.tech/topics/shaders.md>), [ui](<https://devfeed.tech/topics/ui.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [gpu](<https://devfeed.tech/tags/gpu.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [programming](<https://devfeed.tech/tags/programming.md>), [shaders](<https://devfeed.tech/tags/shaders.md>), [ui](<https://devfeed.tech/tags/ui.md>)

### AI overview

A tutorial on using Android 13's RuntimeShader API in Jetpack Compose to simulate soft shadows cast by a user's finger, stylus, or pointing device. It models the finger as an oriented capsule in 3D space and computes light visibility using cone and spherical-cap intersections.

### Source excerpt

I recently realized that I have never discussed graphics programming on this blog, and decided it was time to correct this. A few years ago, Android 13 introduced the RuntimeShader API that allows you to write custom GPU shaders and apply them to UI elements. In this blog post I will show you how this API can be used to simulate shadows projected by the user's finger (or stylus/pointing device) onto your UI.

## Optimizing Jetpack Compose Transform Computations by Merging Functions

DevFeed: [Optimizing Jetpack Compose Transform Computations by Merging Functions](<https://devfeed.tech/articles/merge-your-computations-25612.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2025/merge-your-computations/>)

Author: Romain Guy

Published: 2025-05-15T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Code](<https://devfeed.tech/topics/code.md>), [Compose](<https://devfeed.tech/topics/compose.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [inlining](<https://devfeed.tech/topics/inlining.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [code](<https://devfeed.tech/tags/code.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [function](<https://devfeed.tech/tags/function.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [inlining](<https://devfeed.tech/tags/inlining.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [merge](<https://devfeed.tech/tags/merge.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explains how merging or manually inlining low-level functions can remove duplicated work in performance-sensitive code. Using Jetpack Compose matrix transformations as an example, it describes eliminating unnecessary temporary matrices and intermediate computations.

### Source excerpt

There is a simple but often overlooked technique to optimize performance-sensitive code: merging (or manually inlining) functions. We often build series of low-level functions that execute various computations that we then combine to perform higher-level tasks. When taken in isolation, each of those functions does exactly what it should and might even be perfectly optimized. However, when a series of thosefunctions work together, unnecessary or duplicated work might appear. Let's look at a concrete example taken from the Jetpack Compose code base. To apply the various geometric transforms that may affect a layer, Compose needs to build a matrix that combines all the transformations exposed by its APIs:

## Eliminating Array Bounds Checks

DevFeed: [Eliminating Array Bounds Checks](<https://devfeed.tech/articles/eliminating-array-bounds-checks-25610.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2025/eliminating-array-bounds-checks/>)

Author: Romain Guy

Published: 2025-05-13T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Memory Safety](<https://devfeed.tech/topics/memory-safety.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Exception](<https://devfeed.tech/topics/exception.md>), [toolchain](<https://devfeed.tech/topics/toolchain.md>), [inlining](<https://devfeed.tech/topics/inlining.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [developer](<https://devfeed.tech/tags/developer.md>), [exception](<https://devfeed.tech/tags/exception.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [inlining](<https://devfeed.tech/tags/inlining.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [memory-safety](<https://devfeed.tech/tags/memory-safety.md>), [performance](<https://devfeed.tech/tags/performance.md>), [toolchain](<https://devfeed.tech/tags/toolchain.md>)

### AI overview

This tutorial explains how Android Runtime array bounds checks protect memory safety but can add unnecessary instructions. It shows how a simple explicit check can help the compiler eliminate those checks in a fixed-size array, reducing the example from 136 to 60 arm64 instructions.

### Source excerpt

The Android Runtime (ART) offers a nice memory safety feature when accessing the content of an array. The indices you use are automatically checked against the bounds of the array to prevent unsafe memory accesses. To achieve this, ART generates extra machine instructions to throw an ArrayIndexOutOfBoundsException when the index is invalid. Here is a simple Kotlin example: 1fun scaleZ(values: FloatArray, scale: Float) = values[2] * scale After translation to arm64 assembly, we obtain the following result:

## How Field Names Affect Performance in Android ART

DevFeed: [How Field Names Affect Performance in Android ART](<https://devfeed.tech/articles/naming-is-hard-25602.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/naming-is-hard/>)

Author: Romain Guy

Published: 2024-12-19T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [LineageOS](<https://devfeed.tech/topics/lineageos.md>), [Code](<https://devfeed.tech/topics/code.md>), [Caching](<https://devfeed.tech/topics/caching.md>), [Benchmark](<https://devfeed.tech/topics/benchmark.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [benchmarks](<https://devfeed.tech/tags/benchmarks.md>), [cache](<https://devfeed.tech/tags/cache.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explains how field naming can affect object field layout and memory-access performance in Android's Android Runtime (ART). In the supplied benchmark, renaming a field made the code 40% faster, because the fields were placed at different memory offsets and could trigger an L1 cache miss.

### Source excerpt

Before we dive into today's topic, I would like to make it clear that what follows is specific to how Android, and more precisely the Android RunTime (ART), works. Some of what follows applies to other environments as well, but the main twist is about Android. If you have read my previous articles, you should know by now that seemingly small or irrelevant changes can have a large impact on performance. So let's look at another one! We'll start our journey with a class containing a bunch of fields. What they are and what they mean isn't really relevant for now, let's just imagine we are dealing with a fairly large object1:

## The Path Not Taken

DevFeed: [The Path Not Taken](<https://devfeed.tech/articles/the-path-not-taken-25607.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/the-path-not-taken/>)

Author: Romain Guy

Published: 2024-12-16T00:00:00Z

Content type: article

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Benchmark](<https://devfeed.tech/topics/benchmark.md>), [Algorithm](<https://devfeed.tech/topics/algorithm.md>), [cpu](<https://devfeed.tech/topics/cpu.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>)

Tags: [algorithm](<https://devfeed.tech/tags/algorithm.md>), [android](<https://devfeed.tech/tags/android.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [benchmarks](<https://devfeed.tech/tags/benchmarks.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explains how benchmark data patterns can produce misleading performance results. Ordered pixel values allow branch prediction to work almost perfectly, while randomized values cause many branch misses and make the benchmark about 2.3 times slower. It then shows how a branchless implementation can restore comparable performance for randomized data on Android.

### Source excerpt

In the last post, we saw that benchmarks don't always measure what we think they measure. Let's look at another instance of this problem today, starting with this rather simple benchmark: 1@RunWith(AndroidJUnit4::class) 2class DataBenchmark { 3 @get:Rule 4 val benchmarkRule = BenchmarkRule() 5 6 // Generate data in [0..255] 7 private val data = IntArray(65_536) { 8 it % 256 9 } 10 11 @Test 12 fun processData() { 13 var sum = 0f 14 benchmarkRule.measureRepeated { 15 for (d in data) { 16 if (d < 128) { 17 sum += d / 128f 18 } 19 } 20 } 21 BlackHole.consume(sum) 22 } 23} This benchmark tests an algorithm that processes an array of values between 0 and 255 (8-bit pixels for instance), and computes the sum of the normalized values for pixels less than 128.

## Avoiding Compiler Elimination in Code Microbenchmarks

DevFeed: [Avoiding Compiler Elimination in Code Microbenchmarks](<https://devfeed.tech/articles/you-are-going-to-need-it-25608.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/you-are-going-to-need-it/>)

Author: Romain Guy

Published: 2024-12-13T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [benchmarking](<https://devfeed.tech/topics/benchmarking.md>), [Code](<https://devfeed.tech/topics/code.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Assembly](<https://devfeed.tech/topics/assembly.md>), [Benchmark](<https://devfeed.tech/topics/benchmark.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [benchmarking](<https://devfeed.tech/tags/benchmarking.md>), [benchmarks](<https://devfeed.tech/tags/benchmarks.md>), [code](<https://devfeed.tech/tags/code.md>), [compare](<https://devfeed.tech/tags/compare.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [measurement](<https://devfeed.tech/tags/measurement.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explains how compiler and runtime optimizations can eliminate the computation being measured in a microbenchmark. Using a comparison between value.pow(2f) and value * value, it shows why inspecting generated code and introducing a carefully placed side effect are necessary for a valid measurement.

### Source excerpt

Optimizing code can be a difficult task because there are so many traps you need to avoid at every step of the way. Today I want to focus on one of the (numerous) benchmarking traps, which you may have run into, and that I myself encounter regularly. Let's imagine you are trying to optimize code, and you notice the use of a value.pow(2f). One obvious way to optimize this is to replace the function call with a multiplication (value * value), but is it worth it? Since you are a diligent engineer, you decide to write a microbenchmark to compare before and after:

## Optimization, Step by Step

DevFeed: [Optimization, Step by Step](<https://devfeed.tech/articles/optimization-step-by-step-25603.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/optimization-step-by-step/>)

Author: Romain Guy

Published: 2024-11-25T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Optimization](<https://devfeed.tech/topics/optimization.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Android](<https://devfeed.tech/topics/android.md>), [pixel](<https://devfeed.tech/topics/pixel.md>), [Algorithm](<https://devfeed.tech/topics/algorithm.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [algorithm](<https://devfeed.tech/tags/algorithm.md>), [android](<https://devfeed.tech/tags/android.md>), [android-14](<https://devfeed.tech/tags/android-14.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>), [pixel](<https://devfeed.tech/tags/pixel.md>)

### AI overview

This tutorial describes step-by-step optimizations to the Kotlin implementation of BlurHash decoding. On a Pixel 6 running Android 14, the changes made decoding a fixed blur hash into a 384x384 image up to 4.35 times faster; one optimization using direct character access and a lookup table improved performance by roughly 5%.

### Source excerpt

BlurHash is a compact representation of placeholders for images. A blur hash is encoded as a short string that can be rendered to a bitmap at runtime to display a "blurry" version of the source image. The way it works remind me of how spherical harmonics are used in 3D rendering engines to efficiently encode irradiance. I recently remembered that I had been meaning to look at the Kotlin implementation of BlurHash to see if there was a way to make it faster. I looked up the KMP port and after a few changes, I was able to make decoding a blur hash up to 4.35x faster on a Pixel 6 running Android 14. For all the measurements mentioned in this article, I decoded a fixed blur hash to a 384x384 image. The original code took 24.4 ms to do this when running at full speed, and 41.5 ms when locking the CPU clocks. This is way too long considering the low resolution of the image.

## A Micro-optimization You Will Never Need

DevFeed: [A Micro-optimization You Will Never Need](<https://devfeed.tech/articles/a-micro-optimization-you-will-never-need-25595.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/a-micro-optimization-you-will-never-need/>)

Author: Romain Guy

Published: 2024-11-10T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Optimization](<https://devfeed.tech/topics/optimization.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Code](<https://devfeed.tech/topics/code.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [compilation](<https://devfeed.tech/tags/compilation.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [developer](<https://devfeed.tech/tags/developer.md>), [devices](<https://devfeed.tech/tags/devices.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [low-power](<https://devfeed.tech/tags/low-power.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article presents a Kotlin micro-optimization that counts leading zeroes so comparisons can use smaller constants encoded directly in AArch64 instructions. The change reduces the compiled function from 21 to 18 instructions, with an estimated performance difference of about 0.5% on a Pixel 8 and around 11% on a Pixel 2.

### Source excerpt

Today I would like to show you a micro-optimization I recently used more for the fun of it than for its real impact. It's an interesting trick that you should never bother to use, nor worry about. It starts from a piece of Kotlin code that looked a bit like this (the original version used named constants, but I replaced them with their actual values for clarity in this context):

## Optimizing Digit Counting for Kotlin Long Values

DevFeed: [Optimizing Digit Counting for Kotlin Long Values](<https://devfeed.tech/articles/down-another-rabbit-hole-25597.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/down-another-rabbit-hole/>)

Author: Romain Guy

Published: 2024-05-27T00:00:00Z

Content type: article

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Code](<https://devfeed.tech/topics/code.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [floating-point](<https://devfeed.tech/tags/floating-point.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [numbers](<https://devfeed.tech/tags/numbers.md>), [operator](<https://devfeed.tech/tags/operator.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explores ways to count the decimal digits in positive Kotlin Long values without relying on floating-point log10, which cannot represent every Long value exactly. It compares a straightforward branching approach with a binary-search solution and reports faster execution for the latter on a Pixel 6.

### Source excerpt

Jake Wharton recently caused me to go down yet another silly optimization rabbit hole when he nonchalantly linked to a piece of code used to count the number of digits in a Long during a Slack conversation about Kotlin's lack of ternary operator. This of course triggered folks like Madis Pink and me to want to optimize it... Counting digits Link to heading The simplest way to count the number of digits would be to compute log10(n).toInt() + 1, where n is our input number. Unfortunately logarithmic functions like Kotlin's log10 are only defined for floating point numbers. If our input is an Int or a Long, we could first convert to Double and then call log10, but not all Long values can be stored in a Double (any value above 2^53), and we would have to special case 0. We must therefore find a different solution1.

## Optimizing Rectangle-Overlap Tests by Removing Conditional Branches

DevFeed: [Optimizing Rectangle-Overlap Tests by Removing Conditional Branches](<https://devfeed.tech/articles/down-a-rabbit-hole-25596.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/down-a-rabbit-hole/>)

Author: Romain Guy

Published: 2024-05-18T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Optimization](<https://devfeed.tech/topics/optimization.md>), [Code](<https://devfeed.tech/topics/code.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Benchmark](<https://devfeed.tech/topics/benchmark.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This article examines optimizing rectangle-overlap tests in Kotlin. It compares generated assembly, replaces logical operators with bitwise operators to remove conditional branches, and reports a 1.7x speedup in a benchmark on a Google Pixel 6.

### Source excerpt

I recently discussed an optimization that I worked on following Leland's successful nerd snipe. That, however, was not the end of it. He also needed to test for intersecting/overlapping rectangles. The most obvious way to achieve this is pretty straightforward: 1// A rectangle is defined by its left (l), top (t), 2// right (r), and bottom (b) coordinates 3data class Rect(val l: Int, val t: Int, val r: Int, val b: Int) { 4 fun overlaps(other: Rect) = 5 l < other.r && other.l < r && t < other.b && other.t < b 6} The source code is nice and tidy, but the generated assembly is less than ideal (as always, the code was optimized with R8 first):

## Practical Optimizations at Android Makers 2024

DevFeed: [Practical Optimizations at Android Makers 2024](<https://devfeed.tech/articles/practical-optimizations-at-android-makers-2024-25604.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/practical-optimizations-at-android-makers-2024/>)

Author: Romain Guy

Published: 2024-05-06T00:00:00Z

Content type: article

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [articles](<https://devfeed.tech/tags/articles.md>), [blog](<https://devfeed.tech/tags/blog.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack](<https://devfeed.tech/tags/jetpack.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>), [programming](<https://devfeed.tech/tags/programming.md>), [talk](<https://devfeed.tech/tags/talk.md>), [talks](<https://devfeed.tech/tags/talks.md>), [techniques](<https://devfeed.tech/tags/techniques.md>)

### AI overview

A talk at Android Makers 2024 discusses low-level optimizations implemented in Jetpack Compose, their performance impact, and the programming techniques behind them.

### Source excerpt

I recently gave a talk called Practical Optimizations at Android Makers 2024. The talk is focused on some of the low-level optimizations we implemented in Jetpack Compose, their impact on performance, and the programming techniques behind them. You will likely find this talk interesting if you've been enjoying the articles about performance and optimizations on this blog. Enjoy!

## Readability of Optimized Kotlin Code

DevFeed: [Readability of Optimized Kotlin Code](<https://devfeed.tech/articles/readability-of-optimized-kotlin-code-25605.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/readability-of-optimized-kotlin-code/>)

Author: Romain Guy

Published: 2024-05-03T00:00:00Z

Content type: article

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>), [API](<https://devfeed.tech/topics/api.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [api](<https://devfeed.tech/tags/api.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [data-structure](<https://devfeed.tech/tags/data-structure.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article explains how Kotlin can keep low-level, micro-optimized code readable while preserving efficiency. It demonstrates a type-safe 8x8 grid encoded as a bitfield, using value classes and operator overloading for optimized rectangle and cell operations.

### Source excerpt

Leland and I were recently discussing how to best implement a new data structure to speed up a specific aspect of Jetpack Compose. He came up with a great idea, and nerd sniped me in the process. The problem was to efficiently encode the occupancy of an 8x8 grid represented as a Long (each bit representing a cell in the grid). After coming up with the bit twiddling code that quickly "rasterizes" a rectangle into the grid as a bitfield, I found myself thinking about how incredibly helpful Kotlin can be at making low-level/micro-optimized code easy to read1 for users of an API.

## Speeding up isBlank()

DevFeed: [Speeding up isBlank()](<https://devfeed.tech/articles/speeding-up-isblank-25606.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/speeding-up-isblank/>)

Author: Romain Guy

Published: 2024-02-05T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Compose](<https://devfeed.tech/topics/compose.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Benchmark](<https://devfeed.tech/topics/benchmark.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [benchmarks](<https://devfeed.tech/tags/benchmarks.md>), [compilation](<https://devfeed.tech/tags/compilation.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [jvm](<https://devfeed.tech/tags/jvm.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article examines the JVM bytecode generated for Kotlin's isBlank() implementation and shows how replacing its generic iteration with traditional loops can improve performance. In benchmarks using 1,000 strings, the revised implementation is reported as 60% faster with zero allocations, while a further optimization reaches nearly 65% faster than the original. The final version also reduces ARM assembly instructions from 161 to 53, illustrating how simple abstractions can affect performance in some workloads.

### Source excerpt

I was recently optimizing a small part of the Jetpack Compose runtime when I stumbled upon a seemingly harmless API, isBlank(). This API return true if the string it's called on is empty or consists solely of whitespace characters. But is it truly harmless? Let's look at the JVM implementation to get a better sense of what it does: 1public actual fun CharSequence.isBlank(): Boolean = 2 length == 0 || indices.all { this[it].isWhitespace() } Simple and straight to the point. Unfortunately the bytecode tells a very different story:

## Kotlin minOf() and maxOf() Can Allocate Arrays for Four or More Arguments

DevFeed: [Kotlin minOf() and maxOf() Can Allocate Arrays for Four or More Arguments](<https://devfeed.tech/articles/micro-optimizations-in-kotlin-3-25601.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/micro-optimizations-in-kotlin-3/>)

Author: Romain Guy

Published: 2024-01-31T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Library](<https://devfeed.tech/topics/library.md>), [Android](<https://devfeed.tech/topics/android.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [JIT](<https://devfeed.tech/topics/jit.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [jit](<https://devfeed.tech/tags/jit.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [library](<https://devfeed.tech/tags/library.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article examines how Kotlin's minOf() and maxOf() handle four or more arguments on Android and the JVM. The variadic implementation can allocate an array at the call site, increasing execution time in tight loops; a four-parameter specialization removes those allocations in the discussed benchmarks.

### Source excerpt

The Kotlin standard library is a wonderful set of APIs, but it sometimes hides... interesting surprises. So today let's took at the innocent looking minOf() and maxOf() functions. These functions let you perform a min/max on a series of values, instead of just two with the more common min() and max() functions. Both min() and max() are straightforward and simply delegate -- on Android and JVM -- to Math.min()/Math.max() respectively, which you can assume to be implemented with intrinsics (and are on Android).

## Optimizing Jetpack Compose with a Fast Cube Root Approximation

DevFeed: [Optimizing Jetpack Compose with a Fast Cube Root Approximation](<https://devfeed.tech/articles/going-old-school-25598.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/going-old-school/>)

Author: Romain Guy

Published: 2024-01-25T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Compose](<https://devfeed.tech/topics/compose.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Algorithm](<https://devfeed.tech/topics/algorithm.md>), [implementation](<https://devfeed.tech/topics/implementation.md>)

Tags: [algorithm](<https://devfeed.tech/tags/algorithm.md>), [android](<https://devfeed.tech/tags/android.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [math](<https://devfeed.tech/tags/math.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>), [snippet](<https://devfeed.tech/tags/snippet.md>)

### AI overview

The article explains how a fast cube root approximation can optimize Jetpack Compose. It applies a float-bit estimation and two Newton-Raphson refinement steps, improving color interpolation by 8% and 2D cubic-easing animations by 17%.

### Source excerpt

While looking for optimization opportunities in various parts of Jetpack Compose, I recently discovered that calling the cube root function was taking a non-neligible amount of times in two areas of the Toolkit: when evaluating cubic Bézier easing curves and when interpolating colors through the OkLab color space. Working on graphics projects taught me that approximations can often be powerful optimization tools, so I decided to come up with an approximation of cbrt()1:

## A Better Hash Map -- 1

DevFeed: [A Better Hash Map -- 1](<https://devfeed.tech/articles/a-better-hash-map-1-25594.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/a-better-hashmap/>)

Author: Romain Guy

Published: 2024-01-20T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Compose](<https://devfeed.tech/topics/compose.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Android](<https://devfeed.tech/topics/android.md>), [Cache](<https://devfeed.tech/topics/cache.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [compose](<https://devfeed.tech/tags/compose.md>), [data-structures](<https://devfeed.tech/tags/data-structures.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack-compose](<https://devfeed.tech/tags/jetpack-compose.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [memory](<https://devfeed.tech/tags/memory.md>), [performance](<https://devfeed.tech/tags/performance.md>), [storage](<https://devfeed.tech/tags/storage.md>)

### AI overview

This article examines hash maps in Jetpack Compose and introduces ScatterMap as a more memory-efficient alternative for the toolkit's use cases. It describes reduced per-entry overhead, allocation-free operations in several cases, linear storage for improved cache behavior, and performance that is better than or comparable to existing map implementations, based on benchmark results from a Pixel 6 running Android 13.

### Source excerpt

Hash maps are extremely common data structures, and Jetpack Compose unsurprisingly takes advantage of them for various tasks. Kotlin makes it easy to create a new mutable hash map by calling the mutableMapOf() function. Most developer will -- and should -- stop there, and use the map however they need to. Things are however a bit different when working on a toolkit like Jetpack Compose as we need to ensure the toolkit's behavior is as unintrusive as possible for the app.

## Micro-optimizations in Kotlin -- 2

DevFeed: [Micro-optimizations in Kotlin -- 2](<https://devfeed.tech/articles/micro-optimizations-in-kotlin-2-25600.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/micro-optimizations-in-kotlin-2/>)

Author: Romain Guy

Published: 2024-01-16T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Code](<https://devfeed.tech/topics/code.md>), [inlining](<https://devfeed.tech/topics/inlining.md>), [Android](<https://devfeed.tech/topics/android.md>), [Assembly](<https://devfeed.tech/topics/assembly.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [inlining](<https://devfeed.tech/tags/inlining.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

This article examines micro-optimizations for Kotlin's Float.sign and Double.sign APIs. It explains their handling of negative and positive values, signed zero, and NaN, then compares the Kotlin implementation with Android's generated AArch64 assembly. The article shows how inlining and intrinsics eliminate function calls and translate the implementation into bit manipulation.

### Source excerpt

In the previous post, we saw how we could micro-optimize Int.sign to save a few instructions. We are now going to turn to Float.sign (and by extension Double.sign). Float.sign returns the sign of single-precision float value as a single-precision float value. While similar to Int.sign, this API must handle a special cases: Not-a-Number (NaN). The exact behavior of the API is that it will return: -1.0f if the value is negative +/-0.0f if the value is zero (floats can encode both positive and negative zero) 1.0f if the value is positive NaN if the value is NaN An easy way to implement this API ourselves is to return the input when the input equals 0.0f or NaN, and to return the input's sign copied onto 1.0f otherwise. Translated to code, we can write:

## Micro-optimizations in Kotlin -- 1

DevFeed: [Micro-optimizations in Kotlin -- 1](<https://devfeed.tech/articles/micro-optimizations-in-kotlin-1-25599.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/micro-optimizations-in-kotlin-1/>)

Author: Romain Guy

Published: 2024-01-15T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Android](<https://devfeed.tech/topics/android.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [code](<https://devfeed.tech/tags/code.md>), [compose](<https://devfeed.tech/tags/compose.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [jetpack](<https://devfeed.tech/tags/jetpack.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [libraries](<https://devfeed.tech/tags/libraries.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>)

### AI overview

A technical article examines micro-optimizations in Kotlin and Jetpack Compose, explaining why low-level performance can matter in frequently invoked library code. It introduces kotlin-explorer, a desktop tool for viewing Kotlin as dex bytecode and ARM 64-bit assembly, and uses it to inspect optimization opportunities.

### Source excerpt

While my work responsibilities do not leave me much time to write code nowadays, I have managed to make a few small contributions to Jetpack Compose in the last few months, mostly focusing on performance. If you are an Android app developer, your performance concerns probably start and stop at a fairly high level 1. I find working on large scale libraries like Compose fascinating because you need to worry about performance not only at a macro level, but also at a micro level. Since parts of the libraries can be invoked frequently (many times per frame for instance), even micro-optimizations can make a difference 2.