Slide 1

Slide 1 text

Justin Brooks The Promise and Peril of Kotlin Multiplatform A New Way to Share Code

Slide 2

Slide 2 text

The Status Quo

Slide 3

Slide 3 text

CPU-Native Code C++ / C / Swift • Debugging is annoying • C interop is sometimes a pain (JNI, Swift/C++ interop is new) • C interop is sometimes not as free as you think (Java Native Interface) • Misses advantages of virtual machines with JIT (like the Android Runtime) • Can bloat binary size unnecessarily • Misses JIT-level optimizations (especially pro fi le guided optimizations)

Slide 4

Slide 4 text

JavaScript • Debugging is painful • Performance characteristics can depend on the host VM • Misses platform-speci fi c optimizations • Interop overhead • “Smart View” problems

Slide 5

Slide 5 text

Xamarin / Mono • Debugging is painful • Build-time complexity incorporating msbuild • Slow, generational stop-the-world GC • Misses advantages of platform-native virtual machines • ART pro fi le-guided optimizations • LLVM JIT negatively impacts startup performance, which is already bad

Slide 6

Slide 6 text

Kotlin Multiplatform

Slide 7

Slide 7 text

Not a library. Not a framework.

Slide 8

Slide 8 text

A Quick Tangent on Compilers

Slide 9

Slide 9 text

int square(int num) { return num * num; } de fi %2 = alloca i32, align 4 store i32 %0, ptr %2, align 4 call void @llvm.dbg.declare(metadata ptr %2, metadata !16), !dbg !17 %3 = load i32, ptr %2, align 4, !dbg !18 %4 = load i32, ptr %2, align 4, !dbg !19 %5 = mul nsw i32 %3, %4, !dbg !20 ret i32 %5, !dbg !21 }

Slide 10

Slide 10 text

int square(int num) { return num * num; } de fi ne dso_local noundef i32 @_Z6squarei(i32 noundef %0) #0 !dbg !10 { %2 = alloca i32, align 4 store i32 %0, ptr %2, align 4 call void @llvm.dbg.declare(metadata ptr %2, metadata !16), !dbg !17 %3 = load i32, ptr %2, align 4, !dbg !18 %4 = load i32, ptr %2, align 4, !dbg !19 %5 = mul nsw i32 %3, %4, !dbg !20 ret i32 %5, !dbg !21 }

Slide 11

Slide 11 text

MODULE_FRAGMENT name: FILE fqName: fi FUN name:square visibility:public modality:FINAL <> (n:kotlin.Int) returnType:kotlin.Int VALUE_PARAMETER name:n index:0 type:kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from='public fi CALL 'public fi $this: GET_VAR 'n: kotlin.Int declared in .square' type=kotlin.Int origin=null other: GET_VAR 'n: kotlin.Int declared in .square' type=kotlin.Int origin=null fun square(n: Int): Int { return n * n }

Slide 12

Slide 12 text

MODULE_FRAGMENT name: FILE fqName: fi leName:sources/main.kt FUN name:square visibility:public modality:FINAL <> (n:kotlin.Int) returnType:kotlin.Int VALUE_PARAMETER name:n index:0 type:kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from='public fi nal fun square (n: kotlin.Int): kotlin.Int declared in ' CALL 'public fi nal fun times (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int $this: GET_VAR 'n: kotlin.Int declared in .square' type=kotlin.Int origin=null other: GET_VAR 'n: kotlin.Int declared in .square' type=kotlin.Int origin=null fun square(n: Int): Int { return n * n }

Slide 13

Slide 13 text

RISC-V ARM X64

Slide 14

Slide 14 text

RISC-V ARM X64

Slide 15

Slide 15 text

Compiler Backends: Stable *

Slide 16

Slide 16 text

KMP is compiler orchestration (a build system plugin and IDE tooling)

Slide 17

Slide 17 text

Kotlin Mutliplatform (KMP)

Slide 18

Slide 18 text

expect & actual Delegating to Platforms

Slide 19

Slide 19 text

> Task :common:compileDebugKotlinAndroid FAILED e: Expected class ‘Platform' has no actual declaration in module for JVM expect class Platform {}

Slide 20

Slide 20 text

• All Kotlin Common • Delegate to platforms with expect & actual • Glue for platform-native libraries • Application • Kotlin all the way down (Compose Multiplatform) • Library • For Kotlin Multiplatform • For platform targets (XCFramework, Android Archive, NPM Package) How What Lots of Options

Slide 21

Slide 21 text

Some Good Third-Party Libraries • cashapp/SQLDelight • square/okio • ktorio/ktor • And a weird one (cashapp/ Redwood) • Kotlin/kotlinx.serialization • Kotlin/kotlinx-datetime • Kotlin/kotlinx-io • Kotlin/kotlinx.collections.immutable Some Good First Party Libraries

Slide 22

Slide 22 text

Peril • N+1 Problem • Kotlin/Native doesn’t support vararg parameters - so Kotlin common is missing String.format. • Building JS-native NPM packages is onerous. • Sometimes you want (or need) API boundaries to be di ff erent between platform targets. Doable but a little awkward. • Pure Swift dependencies aren’t supported for Apple targets.

Slide 23

Slide 23 text

Knapsack (Demo)

Slide 24

Slide 24 text

common/ • Authentication initial password grant & refreshing access token • Network http & json serialization • Caching SQLite & simple key-value storage • Text processing HTML → platform-speci fi c rich text representations

Slide 25

Slide 25 text

Directory Files Lines Blanks Comments Code Complexity Common 32 Kotlin 971 148 8 815 64 knapsack- android 12 Kotlin 784 79 29 676 17 knapsack-iOS 10 Swift 442 76 68 298 10

Slide 26

Slide 26 text

Share when it helps; otherwise, don’t.

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

https://github.com/Faithlife/FaithlifeOAuth-Mobile https://net fl ixtechblog.com/net fl ix-android-and-ios-studio-apps-kotlin-multiplatform-d6d4d8d25d23 https://kotlinlang.org/lp/mobile/case-studies/cash-app https://youtrack.jetbrains.com/issue/KT-47241/Kotlin-Variation-That-Compiles-Down-To-IL https://github.com/jzbrooks/Knapsack