Hi, anyone care to share how is kotlin inject/anvi...
# kotlin-inject
u
Hi, anyone care to share how is kotlin inject/anvil in production? I'm a 500kloc dagger/anvil app.
e
It's great 😁
u
No hickups or surprises?
e
Not really, a couple of bugs have popped up over the years when I start doing weird things (e.g. injecting a typealias that targets a typealias) but for the most part it's been solid. kotlin-inject-anvil has been absolutely amazing. The only issue I can think of is that assisted parameters in a constructor don't work, but they're aware of the issue, and there's a workaround until it gets fixed. I've been using it for both KMP and Android only projects.
u
Any chance you could share how big is your project? kloc/modules?
e
My current project is newer so it's around 30 modules, not sure about klocs. It's scaling up quickly though, and I haven't had any growing pains yet.
u
Do you keep all the k-i annotated code in
commonMain
?
e
Not as a rule, but I try to when possible.
I almost always generate the code for each target's source set though, and don't generate code into the common (i.e.
metadataMain
) source set
u
Could you please explain what does "generate the code for each target's source set.." mean? Doesn't the k-i generated code always stay in `commonMain`if my k-i annotation is in
commonMain
?
e
It depends on which KSP configuration you use. I think I wrote something in the wiki about this. I'll check now.
u
> However, certain scenarios instead require generating code for all target source sets (e.g. if a
Component
or any of its ancestors are an
expect
type, and the
actual
implementation provides platform specific bindings). I'm a KMP noob, but what does this mean? Aren't the
@Component
always abstract classes? Ancestor = parent component to the component?
k
We use kotlin-inject-anvil in the Bitkey mobile app (Android & iOS, mostly KMP code), ~170 KMP modules give or take https://github.com/proto-at-block/bitkey/blob/main/app/settings.gradle.kts
👀 1
u
https://github.com/proto-at-block/bitkey/blob/main/app/gradle/libs.versions.toml#L52 Is it a pure
kotlin inject
for DI or some sort of concurrent DI libs situtation?
How is your build speed? Any issues when in production?
k
That's an outdated version variable, we used to use dagger-anvil on Android only
We used to use manual DI (no frameworks, constructing DI graph manually, it was a huge pain) before migrating to kotlin-inject-anvil and did some benchmarks to compare. In terms of build times, you can't beat manual DI graph (no code generation), but the impact was fairly minimal.
Benchmarks with using kotlin-inject-anvil and KSP 2.0 iOS: - ~2 sec slowdown in clean builds - ~4 sec slowdown in incremental builds with ABI changes - ~11 sec slowdown in incremental builds with non-ABI changes Android: - <1 sec slowdown in clean builds - ~2.9 sec slowdown in incremental builds with ABI changes - ~1.7 sec slowdown in incremental builds with non-ABI changes
Also worth noting that we tried KSP 1.0 initially and saw a big 150% slowdown across the board in benchmarks, KSP 2.0 makes a huge difference
Also worth noting that there are other variables that will impact this: how benchmarks are measured, the machine that they run on, your module structure (eg if you use api/impl module split), how clean your dependency graph is.
u
the 3 number per platform you mention, those are compared to manual DI or dagger/anvil?
btw isnt the ios non-abi change being larger than abi change strange? isnt it supposed to be other way around?
k
compare manual DI to kmp kotlin-inject-anvil
u
also, I'm looking at the library's commits.. the ksp2 was landed 2 weeks ago - are you using a snapshot or something?
k
btw isnt the ios non-abi change being larger than abi change strange?
yeah, it is strange, I never figured out why that is 🙂
u
out of curiosity, do you know whats your total build time for ios vs android?
Benchmarks from a few months ago:
We also have migrated UI to CMP recently so the iOS builds are probably a bit slower now
u
so you can just swap ksp1 for 2 in app code? I though it needed support in the k-i lib https://github.com/evant/kotlin-inject/commits/main/
k
Oh I guess I haven't realized that kotlin-inject was on ksp 1 at the time, I know kotlin-inject-anvil has been using ksp 2 for some time.
u
hmm damn, incremental builds for ios are over a minute? and longer than clean builds?
k
Yeah, XcFramework linking is super slow for us. I think ~95% of our code is in KMP.
u
but why is it slow-er than a clean build, thats super strange
k
Yeah, not sure, we haven't looked into too deeply, I can only speculate but maybe K/N caching is slow?
u
slow, sure, but slower than clean build? odd massive thanks for the insight though!
😅 1
k
There's also K/N incremental compilation that we haven't tried yet but would be interesting to see if 1) it works, and/or 2) has positive impact.
Also, fun fact, ObjC headers from our umbrella framework that we use on iOS is 68k LoC!
u
maybe youre building all of the abi architectures?
I think yes, we might be building for at least 2 architectures, it's not super well optimized at the moment
u
So I presume you develop for android & then once done, just make it work for ios?
k
basically!