Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Promise and Peril of Kotlin Multiplatform

The Promise and Peril of Kotlin Multiplatform

Avatar for Justin Brooks

Justin Brooks

February 10, 2023
Tweet

More Decks by Justin Brooks

Other Decks in Programming

Transcript

  1. 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)
  2. JavaScript • Debugging is painful • Performance characteristics can depend

    on the host VM • Misses platform-speci fi c optimizations • Interop overhead • “Smart View” problems
  3. 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
  4. 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 }
  5. 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 }
  6. MODULE_FRAGMENT name:<main> FILE fqName:<root> 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 <root>.square' type=kotlin.Int origin=null other: GET_VAR 'n: kotlin.Int declared in <root>.square' type=kotlin.Int origin=null fun square(n: Int): Int { return n * n }
  7. MODULE_FRAGMENT name:<main> FILE fqName:<root> 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 <root>' 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 <root>.square' type=kotlin.Int origin=null other: GET_VAR 'n: kotlin.Int declared in <root>.square' type=kotlin.Int origin=null fun square(n: Int): Int { return n * n }
  8. > Task :common:compileDebugKotlinAndroid FAILED e: Expected class ‘Platform' has no

    actual declaration in module <common_debug> for JVM expect class Platform {}
  9. • 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
  10. 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
  11. 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.
  12. 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
  13. 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