Tips and Tricks for the new D8 Compiler from our R&D Team

As you know the new D8 dexer became the default one starting from Android Studio / Android Gradle Plugin 3.1. If your application can be targeted to minSDK >= 19, you can decrease the size of Dalvik byte code for array initialization operations.

Initializing an array is a quite frequent thing in the development of Java and Android applications. So getting the byte code optimized is useful here.

For example, you have defined a set of column names of a table to work with SQLite. Let us get a sample from the Android's documentation:
https://developer.android.com/training/data-storage/sqlite.html#java

// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
    BaseColumns._ID,
    FeedEntry.COLUMN_NAME_TITLE,
    FeedEntry.COLUMN_NAME_SUBTITLE
};

This is how the byte code looks if compiled with DX dexer:

014406: 1230                    |0003: const/4 v0, #int 3 // #3
014408: 2300 4600               |0004: new-array v0, v0, [Ljava/lang/String; // type@0046 
01440c: 1201                    |0006: const/4 v1, #int 0 // #0
01440e: 1a02 8d00               |0007: const-string v2, "_id" // string@008d
014412: 4d02 0001               |0009: aput-object v2, v0, v1
014416: 1211                    |000b: const/4 v1, #int 1 // #1
014418: 1a02 ef00               |000c: const-string v2, "title" // string@00ef
01441c: 4d02 0001               |000e: aput-object v2, v0, v1
014420: 1221                    |0010: const/4 v1, #int 2 // #2
014422: 1a02 ec00               |0011: const-string v2, "subtitle" // string@00ec
014426: 4d02 0001               |0013: aput-object v2, v0, v1

We see that at 0003-0004 a new string array is getting created, and at 0006-0009, 000b-000e, 0010-0013 it is being filled with _id, title, and subtitle strings.

If we would use the new D8 dexer and set the minSdkVersion to 19 in the build.gradle, we would get the following bytecode:

014446: 1a00 8b00               |0003: const-string v0, "_id" // string@008b
01444a: 1a01 f000               |0005: const-string v1, "title" // string@00f0
01444e: 1a02 ec00               |0007: const-string v2, "subtitle" // string@00ec
014452: 2430 4600 1002          |0009: filled-new-array {v0, v1, v2}, [Ljava/lang/String; // type@0046
014458: 0c00                    |000c: move-result-object v0

As you can see, it is tighter due to the fact that instead of performing 3 operations of putting a string into the array, we put indexes of strings which takes 2 16-bit units versus 5 16-bit units with DX.

We have seen so many constructions of that kind in the real world applications, and we are almost sure you have got them too. So why not to get this zero-cost optimization? The size of the byte code should decrease, and the launch time, and performance should become better.

Next time we will tell you about the new optimizer, R8.