```val Context.appGraph: AppGraph get() = (app...
# getting-started
u
Copy code
val Context.appGraph: AppGraph
    get() = (applicationContext as AppGraphProvider).appGraph
I have this simple convenience extension, but it takes
10ms
(in debug) to execute, which is extremely high for what it is if I
inline
it or manually inline it, then it's basically instant as expected Why? Does it have to do with
ContextKt
class loading as that's the first access or something?
👀 1
y
Make sure you're benchmarking properly, using JMH or kotlinx-benchmark. The reality is that any JVM worth its salt would inline this method for you if it's in a hot path
u
Well its not hot path like a loop, but app start up, so called only once Would that change anything?
c
How are you measuring the time?
u
just system.nanos, but its consistent so I'd say there is something
c
If it's called only once at startup, it would be strange if it were consistent, JVM startup is usually not consistent
Can you decompile it? In IntelliJ, at the top, Tools → Kotlin → Show Kotlin Bytecode, click on your property, then Decompile and see what the Java code looks like
That only works in
kotlin("jvm")
projects though
u
I mean consistently 10-30ms if i inline it its 0
y
https://developer.android.com/topic/performance/appstartup/analysis-optimization#improve-startup https://developer.android.com/topic/performance/baselineprofiles/overview#startup-profiles This'll probably fix your problems. It's rarely the right move to
inline
unless there's lambdas involved or you really, really know what you're doing (e.g. reducing boxing with value classes passed as generics)
u
I always was skeptical about the "optimizer will fix it" .. I mean..will it? There's no way to tell unless digging into the R8's output assembly + the startup profiles as you mention
I was mostly curious why this is, I wasn't expecting for extension to have a cost in any sense
c
Can you show the decompiled code?
but yeah if
inline
impacts it, class-loading shenanigans is a likely culprit
âž• 1
u
Copy code
inline val Context.appGraph: AppGraph
    get() = (applicationContext as AppGraphProvider).appGraph
Copy code
val appGraph = appGraph as AppStateHelperGraph
Copy code
# Not inlined
LINENUMBER 23 L3
ALOAD 0
CHECKCAST android/content/Context
INVOKESTATIC sk/ursus/nav3demo/AppRootKt.getAppGraph (Landroid/content/Context;)Lsk/ursus/nav3demo/AppGraph;
DUP
LDC "null cannot be cast to non-null type sk.ursus.nav3demo.AppStateHelperGraph"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkNotNull (Ljava/lang/Object;Ljava/lang/String;)V
CHECKCAST sk/ursus/nav3demo/AppStateHelperGraph
ASTORE 2
Copy code
# inlined
LINENUMBER 23 L3
ALOAD 0
CHECKCAST android/content/Context
ASTORE 4
L4
ICONST_0
ISTORE 5
Somehow the inlined feels too small 😄 I mean where is the field access
y
Are you maybe not using the app graph after? It seems like the casts and such aren't even happening, which is strange. Something fishy is going on, I think
u
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    enableEdgeToEdge()

    val appGraph = appGraph as AppStateHelperGraph
    val appStateHelper = appGraph.appStateHelper
    
    val deeplink = resolveIntent(intent)
    pendingDeeplink.value = deeplink
    setContent {
        AppRoot(appStateHelper, pendingDeeplink)
    }
}