Skip to content

Use Gradle Worker API #2903

@vmishenev

Description

@vmishenev

WIP

Motivation

  1. Currently, Dokka reloads a big classpath for every task. Also, it has reflection magic to support different versions of plugins.
  2. Dokka works parallel badly. For example, the run time on on a project with 100 tasks is 8 minutes.

Proposal

Gradle Worker API can help Dokka to avoid it. But we have 2 options for using it:

  1. Use cached classpath and noIsolation mode (to keep a classpath in a static variable that is shared between tasks). This approach is used in Kapt.
  2. Use processIsolation mode. Dokka task will be executed in worker daemon processes. The running processes with the same classpath can be reused for other tasks. In this case, the classpath is loaded once per process.

We need to choose only one option.
We already have prototypes. @aSemy created one for the second option and there is a prototype for the cached classpath here.

Pros&cons

  • From a performance point of view, processIsolation requires time to run worker processes (default is number of CPU processors) and load classpath in each process. However, if daemons are already running, the time of Dokka executing is the same as for cached classpath.
    My observations:
    Coroutines (precompilied): ~35s (cached classpath) vs ~66s (processIsolation with 8 workers)
    Small project with 100 tasks : ~20s (cached classpath) vs ~60s (processIsolation with 8 workers)
    My hypothesis: the difference in execution time between the two approaches is a constant (for my computer with 8 workers the difference is ~40 sec) to run processes and load classpathes. But the constant depends on the number of workers (e.g. coroutines --max-workers=2 takes 44 sec).
    Also, we can adjust the number of workers (depending on a number of tasks) to get more performance.

  • Stability. noIsolation needs synchronization for a static state. For example, we have a data race with static properties on the IDE part. Also, Kapt experienced OOM issues. Since we use external libraries (and the compiler) and Dokka is not designed for a multithreading environment, some such kinds of problems can appear.

  • Library compatibility. The Gradle documentation says: "External libraries may rely on certain system properties to be set which may conflict between work items. Or a library might not be compatible with the version of JDK that Gradle is running with and may need to be run with a different version. ". But I am not sure that is relevant for our external libraries.

There are other points for choosing an approach. Everybody can share their opinion about it here.

To sum up, I personally vote for the first option. In the case of Dokka, we will increase little bit of time building but stability is more important than performance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementAn issue for a feature or an overall improvementfeedback: Kotlin libsFeedback from Kotlin's internal librariesrunner: Gradle pluginAn issue/PR related to Dokka's Gradle plugin

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions