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

Gradle daemon incredibly slow to start on macOS #215

Open
MidKnightXI opened this issue Mar 28, 2022 · 16 comments
Open

Gradle daemon incredibly slow to start on macOS #215

MidKnightXI opened this issue Mar 28, 2022 · 16 comments

Comments

@MidKnightXI
Copy link

So I created my own image based on the official Gradle one to build React Native app from containers and I'm using the ./gradlew assembleRelease in the /android folder but the daemon is taking more then 2500sec to start (see below).

image

The problem is that when I'm on WSL the build is working just fine (less than 700sec) and I just don't understand why it does not work on macOS (I've an M1 chip)

@marcmesh
Copy link

If you are on Docker Desktop, consider docker/roadmap#7
In a nutshell: Use latest macOS Monterey 12.3, latest Docker Desktop for Apple silicon, and activate Experimental feature

@MidKnightXI
Copy link
Author

If you are on Docker Desktop, consider docker/roadmap#7
In a nutshell: Use latest macOS Monterey 12.3, latest Docker Desktop for Apple silicon, and activate Experimental feature

Excuse me for not giving you that detail but I'm on the latest macOS version with experimental features.

I tried with and without and it's building at that exact same speed

@MidKnightXI
Copy link
Author

MidKnightXI commented Mar 31, 2022

Okay so I published on GitHub the Dockerfile I'm talking about.

I built the image on my Mac and pushed it to the Docker Hub(The 2.1-area was amd64 only which was decreasing perf on my machine), everything looks fine but when I'm trying to build a container using it, the Gradle daemon is starting way faster 70sec ~ (which is normal) but failed to install build-tools;30.0.2 and even if I install it in the base image, the build is failing because of this error.

Full error:

#7 82.88 License for package Android SDK Platform 30 accepted.
#7 82.88 Preparing "Install Android SDK Platform 30 (revision: 3)".
#7 89.88 "Install Android SDK Platform 30 (revision: 3)" ready.
#7 89.88 Installing Android SDK Platform 30 in /sdk/platforms/android-30
#7 89.88 "Install Android SDK Platform 30 (revision: 3)" complete.
#7 89.88 "Install Android SDK Platform 30 (revision: 3)" finished.
#7 89.98 
#7 89.98 FAILURE: Build failed with an exception.
#7 89.98 
#7 89.98 * What went wrong:
#7 89.98 Could not determine the dependencies of task ':app:compileReleaseJavaWithJavac'.
#7 89.98 > Failed to install the following SDK components:
#7 89.98       build-tools;30.0.2 Android SDK Build-Tools 30.0.2
#7 89.98   Install the missing components using the SDK manager in Android Studio.
#7 89.98 
#7 89.98 
#7 89.98 * Try:
#7 89.98 Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
#7 89.98 
#7 89.98 * Get more help at https://help.gradle.org
#7 89.98 
#7 89.98 Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
#7 89.98 
#7 89.98 You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
#7 89.98 
#7 89.98 See https://docs.gradle.org/7.2/userguide/command_line_interface.html#sec:command_line_warnings
#7 89.98 
#7 89.98 BUILD FAILED in 1m 9sUnable to list file systems to check whether they can be watched. The whole state of the virtual file system has been discarded. Reason: Could not query file systems: could not open mount file (errno 2: No such file or directory)
#7 89.98

@keeganwitt
Copy link
Owner

You'd have to install the Android SDK yourself. This image is just Gradle, not anything else.

@MidKnightXI
Copy link
Author

You'd have to install the Android SDK yourself. This image is just Gradle, not anything else.

That's actually what I'm doing.

ENV SDK_URL="https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip" \
    ANDROID_HOME="/sdk" \
    PATH="$PATH:${ANDROID_HOME}/cmdline-tools/bin" \

...

RUN curl -s ${SDK_URL} > /tools.zip \
    && unzip /tools.zip -d ${ANDROID_HOME} \
    && rm /tools.zip

ADD packages.txt /sdk

RUN mkdir -p /root/.android \
    && touch /root/.android/repositories.cfg \
    && ${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} --update \
    && yes | ${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} --licenses

RUN while read -r package; do PACKAGES="${PACKAGES}${package} "; done < /sdk/packages.txt \
    && ${ANDROID_HOME}/cmdline-tools/bin/sdkmanager --sdk_root=${ANDROID_HOME} ${PACKAGES}

package.txt:

platform-tools
extras;google;market_licensing

The thing is that the build is working on amd64 with the gradle daemon but crashing on M1 because of the above Error.

@keeganwitt
Copy link
Owner

keeganwitt commented Apr 12, 2022

I don't have a device with Apple silicon to test on and haven't confirmed the state of Android SDK support on that hardware (though it was my understanding it was supposed to work). One potential workaround would be to use install Rosetta 2 and use --platform linux/amd64.

@danon
Copy link

danon commented Apr 12, 2022

It's also slow on Windows.

Same for WSL on Windows.

@MidKnightXI
Copy link
Author

I don't have a device with Apple silicon to test on and haven't confirmed the state of Android SDK support on that hardware (though it was my understanding it was supposed to work). One potential workaround would be to use install Rosetta 2 and use --platform linux/amd64.

I don't really understand what you mean by using Rosetta, the SDK is already based on amd64 arch:

ENV SDK_URL="https://dl.google.com/android/repository/commandlinetools-linux-8092744_latest.zip"

I also tried with the macOS install but still the same prob

@keeganwitt
Copy link
Owner

I'm talking about the argument to docker run, not the contents of the Dockerfile. The --platform argument allows you to run amd64 based images under emulation. See the documentation here: https://docs.docker.com/desktop/mac/apple-silicon/.

@MidKnightXI
Copy link
Author

I'm talking about the argument to docker run, not the contents of the Dockerfile. The --platform argument allows you to run amd64 based images under emulation. See the documentation here: https://docs.docker.com/desktop/mac/apple-silicon/.

If I do that, my image would be incredibly slow: cf the first screenshot of this issue

@keeganwitt
Copy link
Owner

That's unsurprising, but my understanding is that there's Arm binaries for MacOS, but not for Linux, and hence not any for the Docker image that would be used on that hardware. I'd seen a couple references to compiling the build tools to target Arm, though I haven't found any recent documentation of that.

@keeganwitt
Copy link
Owner

@danon is your use case also regarding Android SDK?

@danon
Copy link

danon commented Apr 17, 2022

No, it's also for a vanilla hello world java gradle.

@keeganwitt
Copy link
Owner

No, it's also for a vanilla hello world java gradle.

In your case is the daemon slow to start also?There are a lot of things that can impact performance. Was the project in a volume? If so, what was the storage driver? Do you get the same poor performance after Gradle has run once and stuff is cached? If you enable verbose logging, does that give any indication what's taking time?

@danon
Copy link

danon commented Apr 18, 2022

@keeganwitt This is a repo you can use to demonstrate it. https://github.com/Danon/Fish When I clone it and run it on gradle:latest the deamon starts for about 60-90 seconds.

@keeganwitt
Copy link
Owner

keeganwitt commented Apr 19, 2022

Documenting some research (using your Fish project as a test):

Measure-Command { docker run --rm -v "${pwd}:/home/gradle/project" -w /home/gradle/project gradle:latest gradle --no-daemon --profile tasks | Out-Default }
Remove-Item build -Recurse
Remove-Item .gradle -Recurse
Measure-Command { gradle --no-daemon --profile tasks | Out-Default }
Remove-Item build -Recurse
Remove-Item .gradle -Recurse

On my machine local is about 10 seconds compared to about a minute in Docker.

To rule in/out the volume as being a performance impact, I created

FROM gradle
RUN mkdir /home/gradle/project
WORKDIR /home/gradle/project
COPY build.gradle.kts .
COPY src/ ./src

Then ran

docker build -t gradle-time .
docker run --rm gradle-time gradle tasks
Measure-Command { docker run --rm gradle-time bash -c 'gradle --no-daemon --profile tasks; cat build/reports/profile/*.html' | Out-Default }

This didn't have any significant performance difference compared to using the volume.

Most of the time spent was in the configuration step, but looking at the output from

Measure-Command { docker run --rm -v "${pwd}:/home/gradle/project" -w /home/gradle/project gradle:latest gradle --no-daemon -d tasks | Tee-Object -FilePath docker.out } | Tee-Object -FilePath docker.out -Append

It wasn't clear that any particular log step took the majority of the time.

My current guess is filesystem performance. Although I'm not sure if that's from the storage driver, the VM, or what.

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

No branches or pull requests

4 participants