Skip to content

Conversation

@elihart
Copy link
Contributor

@elihart elihart commented May 15, 2020

Fixes #423

  • Adds incremental annotation support via Aggregrating mode. Isolating is not possible without removing functionality
  • Removes Litho, since it was never used afaik, was very long out of date, and not worth our time to maintain it
  • The single EpoxyProcessor annotation processor class is split into a separate processor for each type of annotation
  • Several optimizations and memoizations were applied to the processors to speed up their processing time
  • A new annotation processor argument logEpoxyTimings can be set to get a detailed breakdown of how long the processors took and where they spent their time (off by default)
  • Another new argument enableParallelEpoxyProcessing can be set to true to have the annotation processor process annotations and generate files in parallel (via coroutines). This can greatly speed up processing time, but given the nature of parallel processing it is still incubating

With these optimizations and parallel processing, clean builds of a model with 165 @ModelView classes went from 4 seconds to 0.5 seconds. A module with 70 @EpoxyModelClass annotated classes also had a 27% decrease in processing time, also now to 0.5 seconds. We don't yet have any profiling for how much difference the incremental compilation makes, but these other optimizations are likely more impactful.

I will release this as a beta with a major release number

@elihart elihart requested a review from BenSchwab May 18, 2020 18:30
@elihart elihart marked this pull request as ready for review May 18, 2020 18:30
@elihart elihart force-pushed the eli-incap branch 2 times, most recently from 2ea8b2d to 2cfa587 Compare May 20, 2020 22:55
Copy link

@BenSchwab BenSchwab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really cool stuff! Excited to see how the parallel processing works in the wild


// JavacFiler does not properly synchronize its "Set<FileObject> fileObjectHistory" field,
// so parallel calls to createSourceFile can throw concurrent modification exceptions.
val filerSourceFile = synchronized(filer) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do all processor get the same instance of filer? Probably doesn't matter as I don't think processors will be run concurrently

validateAttributesImplementHashCode(generatedModels)
}

logger.writeExceptions()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not necessary but just a thought - it seems like normal exceptions are pretty tractable and likely can be gracefully lazily collected.

Did you find any super weird output with concurrent exceptions like cme's while working on the parallelization? I could imagine that those might leave the program in a weird state and create tons of exceptions. Specially handling them might also be nice to print a message like "CME found, consider disabling experimental parallelization feature and file a ticket with info).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting idea. I did find CME sometimes, or a specific exception from ClassReader. i like the idea of checking for that to tell users to disable parallelization and to report the stacktrace. i didn't find any times where the processor got into a weird state because of it where there were downstream errors

abstract val usesPackageEpoxyConfig: Boolean
abstract val usesModelViewConfig: Boolean

override fun supportedAnnotations(): List<KClass<*>> = mutableListOf<KClass<*>>().apply {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe a little safer to make this final, and have an abstract additionalSupportedAnnotations as it seems like we can't use @CallSuper or something like that


/**
* Returns all of the package config elements applicable to this processor.
*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bunch of extra space here

* The elements that influence the generation of this model.
* eg base model class for @EpoxyModelClass, view class for @ModelView, etc
*/
open fun originatingElements(): List<Element> {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar - might be nice to keep this private and call into an abstract originatingElements methods

@elihart
Copy link
Contributor Author

elihart commented May 23, 2020

I've pushed a 4.0.0-beta1 release if anyone wants to use this right now

@elihart elihart merged commit b9744d2 into master May 23, 2020
@elihart elihart deleted the eli-incap branch May 23, 2020 17:34
@TaxistSamael
Copy link

Thank you a lot for this optimization!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for incremental annotation processing in Gradle

4 participants