Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated components contain a lot of duplication #450

Open
vRallev opened this issue Oct 31, 2024 · 6 comments
Open

Generated components contain a lot of duplication #450

vRallev opened this issue Oct 31, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@vRallev
Copy link

vRallev commented Oct 31, 2024

Probably related to #429, but the issue is so significant that I would consider this a bug. I understand the premise that kotlin-inject is not aiming for the same build and runtime performance as Dagger.

We migrated our middle-sized project from Dagger 2 to kotlin-inject. Our component size grew from 2,566 lines of Java code to 13,430 lines of Kotlin code. This single file slows down kotlinc significantly and voids the gains of removing KAPT from the project at build time.

Further, there is a lot of duplication that also has an impact at runtime. Provider methods get nested deeply, which causes patterns in the file like this:

                                                                         unique = unique,
                                                                          appConfig = appConfig
                                                                        )
                                                                      }
                                                                    ),
                                                                    driverSessionService = function0DriverSessionService
                                                                  )
                                                                }
                                                              )
                                                            ),
                                                            coroutineScope = coroutineScope
                                                          )
                                                        }
                                                      )
                                                    )
                                                  }
                                                )
                                              )
                                            }
                                          )
                                        )
                                      }
                                    )
                                  }
                                )
                              )
                            }
                          ),
                          resourceProvider = resourceProvider
                        )
                      }
                    )
                  },

We have a provider function like this:

@Provides
public fun provideDeviceDataProviderImplDeviceDataProvider(
    deviceDataProviderImpl: DeviceDataProviderImpl
): DeviceDataProvider = deviceDataProviderImpl

When called in-place in the generated component, the code looks like this:

deviceDataProvider = provideDeviceDataProviderImplDeviceDataProvider(
  deviceDataProviderImpl = _scoped.get("com.amazon.bivis.maps.id.DeviceDataProviderImpl") {
    DeviceDataProviderImpl(
      application = application,
      deprecatedVehicleId = provideDeviceIdProviderImplDeprecatedVehicleId(
        deviceIdProviderImpl = _scoped.get("com.amazon.bivis.maps.service.`impl`.DeviceIdProviderImpl") {
          ...
        }
      ),
      unique = unique,
      appConfig = appConfig
    )
  }
)

I left out some details, in total it's 21 lines. These 21 lines are generated 93 times in the component, which makes it close to 2,100 lines of code, which could be reduced to 21 + 93. That is significant. In another example a block is 55 lines and duplicated 34 times.

This adds a lot of overhead at build time, slows the IDE down and is extra overhead at runtime, because all this code needs to be loaded. I'm afraid it will get worse over time when our object graph evolves as small changes to a single provider method could add thousands of lines of generated code.

@evant evant added the bug Something isn't working label Oct 31, 2024
@evant
Copy link
Owner

evant commented Oct 31, 2024

Note: we currently don't have any tests against generated code size, we probably should add some

@sergeshustoff
Copy link
Contributor

Do you by any chance have some cyclic dependencies broken with Lazy or lambda in the dependency graph? When I migrated rather huge project from dagger removing one cyclic dependency reduced the loc by 10 times at least - that's because some optimizations stop working with cycles

@sahilbajaj
Copy link

We are trying to use kotlin-inject in a compose multiplatform app that's soon to go live.

@evant Just curious if this issue is critical enough and if it's planned in the near term roadmap.

@evant
Copy link
Owner

evant commented Jan 12, 2025

Do you by any chance have some cyclic dependencies broken with Lazy or lambda in the dependency graph?

This is almost certainly the case. Cycle detection/handling badly needs to be re-written. I've tried to do that a couple of times now but failed at it. Would love some help getting it right. 😕

@sergeshustoff
Copy link
Contributor

Any thoughts how it should be done? Or how it shouldn't? I'm starting to think in a direction of dagger-like "if it's not scoped always create new instance", but that might be a bit extreme)

@vRallev
Copy link
Author

vRallev commented Jan 15, 2025

Do you by any chance have some cyclic dependencies broken with Lazy or lambda in the dependency graph?

Yes, we definitely did this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants