I really like Jetpack Compose. Between work and personal stuff I have three projects which are each built on top of it. It's great! So far my biggest problem is its name… but that requires some explaining. Welcome to one of the hills I'll die on! What is Jetpack Compose? If you're already familiar w...
I use Docker to run a lot of tools. With the tools all wrapped up in containers, my computers are free of Python and Go and the various other dependencies needed for their use. While this is a nice win for isolation and reproducibility, the user experience is sub-par. To run a tool, I just use docke...
Command-line programs use color to convey additional information and to look pretty. For example, compare the output of ls with and without the --color flag: The color helps convey information in this compact output that would otherwise only be available in more verbose forms (-l). In addition to co...
How many times does the name of a layout file appear in an Android APK? We can build a minimal APK with a single layout file to count the occurrences empirically. Building an Android app with Gradle requires only one thing: an AndroidManifest.xml file with a package. From there we can add a dummy la...
We'll get to the shrinking, but first let's motivate the binary in question. Three years ago I wrote the "Surfacing Hidden Change to Pull Requests" post which covered pushing important stats and diffs into PRs as a comment. This avoids surprises with changes that affect binary size, manifests, and d...
Last year I built a library called Picnic for rendering data tables in monospaced environments like your terminal. Part of rendering the table is calculating what character to use for each wall and each corner separating the cells. Here's a representative output with a bunch of different corner styl...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". Lambda usage in Kotlin feels more pervasive than Java because of the functional nature of t...
I've been porting the AndroidX collection library to Kotlin multiplatform to experiment with binary compatibility, performance, tooling, and the different memory models. Some of the data structures in the library use array-based binary trees to store elements. The Java code has a lot of shifts to re...
I recently played a minor role in helping add Cast support to an Android app. Both the Android app and Cast display are written in Kotlin. The Android Cast SDK relays JSON strings to the JavaScript SDK which invokes your callback with the deserialized equivalent as a JS object. A multiplatform libra...
When writing multiplatform code, Kotlin's three compiler backends each have different memory models which must be considered. JavaScript is single-threaded so you really can do no wrong. The JVM model is arguably too permissive where you can do incorrect things and have them work 99.9% of the time. ...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The assert keyword is quirky Java language syntax used for testing invariants. That is: thi...
I want to remove Google as a single point of failure in my life. In the first blog post on this subject I detailed my setup for backing up Google Photos and Google Drive contents onto my home server and remotely to rsync.net. Left out of that post was a solution for Gmail because I hadn't found one ...
I want to remove Google as a single point of failure in my life. They have two decades of my email. They have two decades of my photos. They have the only copy of thousands of documents, projects, and other random files from the last two decades. Now I trust Google completely in their ability to cor...
In 2010 I built a home server with five 2TB drives. It ran Solaris and ZFS for the redundancy and data checksumming to ensure no data could be lost or corrupted. Just 16 months later five 3TB drives were added to the pool. This computer took the 2600-mile trip to live in San Francisco with me. It th...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". So far in this series the coverage of D8 has been about desugaring of Java 8 language featu...
Kotlin is justifiably lauded for its language features compared to today's Java. It has constructs which allow expressing common patterns with more concise alternatives. An overused example in every intro-to-Kotlin talk or blog post is comparing a Java "POJO" to a Kotlin data class. Here's yet anoth...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". No, that's not a typo! While the optimizations in this series so far have been done by R8 d...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post on R8 covered enum ordinals which then allowed branch elimination to appl...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". Enums are (and have always been!) a recommended way to model a fixed set of constants. Most...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post on R8 covered method outlining which automatically de-duplicated code. Th...
How can we determine the impact of each entry on a zip file's size? It seems like a trivial problem, but things quickly don't add up. There's three built-in ways to read information about the contents of zip file in Java: Mount the zip as a FileSystem using FileSystems.newFileSystem and then access ...
Checked exceptions are a concept that exist only in the Java compiler and are enforced only in source code. In Java bytecode and at runtime in the virtual machine you're free to throw checked exceptions from anywhere regardless of whether they're declared. At least, anywhere except from a instance c...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". I recently wrote about the economics of generated code which talked about performing optimi...
This post is a follow-up to "The Economics of Generated Code" which argued that spending time optimizing generated code is more worthwhile than the same optimizations done in manually-written code. The second example from that post dealt with looking up views, checking for null, and potentially thro...
Among the many things that I've stolen learned from Jesse Wilson is the phrase "the economics of generated code". This captures the idea that the things we value when generating code are different than those we value for code that's manually written. A code generator is only written once but the cod...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post in the series showed R8 (and D8) invoking string methods at compile-time ...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post in the series covered an R8 flag which allows you to specify the return v...
Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post (part 1, part 2) featured R8 performing data-flow analysis of variables i...