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

Ways of caching for speeding up ephemeral CI/CD docker images? (Kotlin) #20449

Closed
AkselAllas opened this issue Apr 12, 2022 · 12 comments
Closed
Labels
a:feature A new functionality in:daemon in:invoking-gradle Running Executing

Comments

@AkselAllas
Copy link

In a persistant VM I can get my gradle build process down to 6-12 sec thanks to Gradle daemon already running.

In an ephemeral CI/CD Docker container (Github Actions) my build takes 1min29 sec due to Gradle daemon needing to start up.

Would it be possible to write a custom optional flag which would try to cache the Gradle daemon to a file, which could be passed as an artifact between the CI/CD pipeline runs?

@AkselAllas AkselAllas added a:feature A new functionality to-triage labels Apr 12, 2022
@asodja
Copy link
Member

asodja commented Apr 12, 2022

Did you try Gradle GitHub action gradle/gradle-build-action@v2?

It should automatically cache cachable things between builds and it might solve your issue. Check README for details.

@AkselAllas
Copy link
Author

I read that gradle-build-action@v2 uses --no-daemon and as such doesn't cache the daemon itself.

gradle/gradle-build-action#113

@asodja
Copy link
Member

asodja commented Apr 12, 2022

I would still suggest trying with the gradle/gradle-build-action@v2.

I think slowness comes from the fact that Gradle on the very first start does some extra work, like generating some jars etc, that might take some time. And I believe gradle-build-action caches that, so the very first start is slow but all next starts should be faster.

Note that daemon is a process and as such, saving it to a file is not that easy. We would have to save all its state to a file for example.

@jbartok jbartok added in:daemon in:invoking-gradle Running Executing and removed to-triage labels Apr 13, 2022
@AkselAllas
Copy link
Author

I have tried actions/cache and gradle-build-action and setup-java

Every result is roughly 1min30sec

Example of uses:

    - name: Setup Gradle
      uses: gradle/gradle-build-action@v2
      - name: Cache Gradle packages and Google Jib cache
        uses: actions/cache@v3
        with:
         path: |
          ~/.gradle
          ~/.cache/google-cloud-tools-java/jib
         key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle.kts') }}
         restore-keys: ${{ runner.os }}-gradle

@AkselAllas
Copy link
Author

My analysis is still that it's the in-memory daemon that is the limiting factor.

@AkselAllas
Copy link
Author

I also tried:

      - name: Setup java
        uses: actions/setup-java@v2
        with:
        distribution: temurin
        java-version: 11

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

Setup java takes 0 sec :D and pipeline is still 1min30sec

@asodja
Copy link
Member

asodja commented Apr 14, 2022

Sorry that you are seeing these issues, I could always be wrong here.

I tried with a dummy Gradle project. I had a very basic setup:

name: Build Gradle project
on:
  push:
jobs:
  build-gradle-project:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout project sources
        uses: actions/checkout@v2
      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2
      - name: Run build with Gradle Wrapper
        run: ./gradlew build

and first-run took cca. 1m, while the second attempt was 22s.

And Gradle part (starting daemon, running tests) of the second attempt was 13s.
Screenshot 2022-04-14 at 10 06 17

So from that I believe daemon start-up is not an issue. But I see that there might be some other issue in the play for your case (maybe compiling build logic/scripts takes long, or tasks are not cached?). But it's difficult to say what is an issue without a reproducer.

Maybe it would be worth to ask also on the community Slack channel if anyone from the community that works with GitHub actions regularly would give a hint.

@asodja
Copy link
Member

asodja commented Apr 14, 2022

Note that I noticed that tasks are not up-to-date since the project level cache is not reused. So to better cache tasks in between builds on CI, you would want to enable build cache like it's described here. But I am not sure if that solves anything for you.

So for task caching in GitHub Actions you would need: gradle/gradle-build-action@v2 caching + build-cache enabled.

@AkselAllas
Copy link
Author

AkselAllas commented Apr 14, 2022

Thanks for the pro guidance @asodja.
Managed to get my rebuild time to 30 sec now on the pipeline with implementing:

org.gradle.caching=true

to gradle.properties

Now my VM runs rebuild in 23 sec while CI/CD runs in 30 sec.
Thanks alot! ❤️

But still 🤔 If I add a pointless Java class to my src files, on my VM it rebuilds in 35 sec, but in CI/CD it takes 1min21sec 🤔

I remember with some configuration I used to have, my "starting gradle daemon" step took like 50+ sec, but now I run ./gradlew --no-daemon and gave up on speeding anything else up.

@AkselAllas
Copy link
Author

If I remove the pointless class, then CI/CD is 30 sec run again and we have compileKotlin FROM-CACHE

@asodja
Copy link
Member

asodja commented Apr 14, 2022

I believe that is an issue with the Kotlin compile task that doesn't support that case (yet). I think Kotlin plugin 1.6.20 has an experimental incremental compilation under the flag kotlin.incremental.useClasspathSnapshot=true. Check also KT-45777. And I suspect it might be stable with the Kotlin 1.7.0 (or not, I am not sure since this is a Kotlin team domain).

But note that this is still experimental as far as I know so I recommend you wait a stable release.

@AkselAllas
Copy link
Author

AkselAllas commented Apr 14, 2022

Thank you for the incredibly insightful responses!

Looking forward to Kotlin plugin 1.7.0

I can die happily now ❤️

@AkselAllas AkselAllas changed the title Would it be possible to cache gradle daemon to a file to speed up ephemeral CI/CD docker images? Ways of caching for speeding up ephemeral CI/CD docker images? (Kotlin) Apr 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:feature A new functionality in:daemon in:invoking-gradle Running Executing
Projects
None yet
Development

No branches or pull requests

3 participants