Do we have to write `inline` to inline lambdas in ...
# compose
s
Do we have to write
inline
to inline lambdas in a function marked with
@Composable
or does the annotation processor optimize it for you?
c
Question is whether it should even be inlined. It might result in huge functions.
l
Inline composables will be supported but they will require the keyword just like normal functions.
Louis I'm not sure I follow what you are proposing
l
@Leland Richardson [G] Instead of inlining the whole function, inlining only its lambda. Example: In the following example, we would not want all of
withPrideHeaderAndFooter
to be inlined at call site.
Copy code
@Composable inline fun withPrideHeaderAndFooter(content: @Composable() () -> Unit) {
    VerticalStack {
        ManyCodeForPrideHeader() // Let's assume there's more code there that we don't want to inline.
        content()
        ManyCodeForPrideFooter() // Same as header.
    }
}
The solution would be that the generated code looks like this at call site:
Copy code
withPrideHeaderAndFooter(before = true) // Runs VerticalStack(before = true) and ManyCodeForPrideHeader()
content() // our lambda is inlined
withPrideHeaderAndFooter(before = false) // Runs VerticalStack(before = false) and ManyCodeForPrideFooter()
instead of looking like this:
Copy code
VerticalStack { // Possibly much code inlined
    ManyCodeForPrideHeader() // Much code inlined
    content() // We just wanted to inline this lambda
    ManyCodeForPrideFooter() // Much code inlined
}
That may be a little more complex to do if
finally
(and
catch
) blocks are allowed in
@Composable
functions.
l
Ah I see what you're getting at. Perhaps this could work in some cases. We have some other optimizations we are planning which are not quite the same but similar in concept
Let about incoming though and more about skipping code we know has not changed
l
I already do this manually (but with two functions, not one with boolean parameter), so inline functions don't inline much apart from the lambda.
This inlining trick might improve performance on Dalvik VMs (Android 4.4 and less). I don't know if it'd be enough to have substantial improvements that make it more usable for these versions though, or if there'll much user base left on these old Android versions by the time Compose is used in production apps.
r
@Suraj Shah Note that Compose does not use an annotation processor
s
@romainguy it doesn't? It has a retention type
BINARY
is that different from
SOURCE
in terms of bloating and processing?
c
Compose is a special compiler plugin, not an annotation processor
👍 1
r
Also note that Compose currently is using minSdk 21, which is ART. Of course that doesn't necessarily mean that it won't change before release, but our current focus is on optimizing for ART's performance characteristics. Of course, ART has also changed a lot since then, so it's a moving target...
c
Does this mean it's no longer recommended to make functions taking lambdas inline functions when targeting ART? (Slightly off-topic, sorry for that)
r
Ah, no, that was just in response to Louis's question about Dalvik
👍 1
I'm not the best person to ask about ART's performance characteristics, so I can't speak to that either way, but my assumption would be that it still makes sense in many (most?) cases, but that if you've got a hot section of code, profiling/benchmarking is always the best bet 🙂
l
the cost/benefit analysis of inline vs not for functions taking lambdas changes in ART, but there are definitely still places where it’s important
allocation’s still aren’t free, but in ART they should be much cheaper, especially in cases where the lambda isn’t retained
l
So I should have written that this inlining trick might improve performance on all devices then! When I wrote for Dalvik, I thought about how allocation is much more expensive there, but even ART might benefit.