출처
: https://blog.asamaru.net/2015/09/29/android-gradle-builds-speed-up/
: http://blog.daum.net/skyapp10047/125
: https://medium.com/@henen/android-studio-속도-향상-스크립트-9887106ad970
: https://www.liaohuqiu.net/posts/speed-up-your-build/
안드로이드 개발을 하면서 여러가지 불만이 있지만 그중에 가장 맘에 들지않는 것 중 하나가 빌드 속도이다.
프로젝트의 규모에 따라 다르겠지만 xcode와의 빌드 시간을 비교하면 전체 빌드의 시간은 비슷한 것 같으나
수시로 하게 되는 빌드는 안드로이드 스튜디오가 훨씬 느리게 느껴진다.
안드로이드 개발시 빌드에 사용되는 Gradle은 많은 유연성을 제공하지만 빌드에 많은 프로세스 비용이 든다는 것이 단점이다.
그래서 빌드 속도를 높일 수 있는 방법을 찾아서 적용해 보았다.
그리고 빌드 시간에 크게 영향을 주는 것 중에는 proguard와 multidex가 포함된다.
proguard는 코드 최적화/난독화 등을 위한 처리이며 multidex는 65K이상의 메소드를 사용할 경우에 대한 대응책으로
사용되며 자세한 내용은 Building Apps with Over 65K Methods에서 참고하면 된다.
메소드 수가 어떻게하면 65K를 넘나 싶을 수 있지만 금방 넘어선다. 라이브러리를 막 추가하다보면 금방 문제를 만나게 된다.
(proguard 등을 통해 메소드 수를 줄일 수 있다). 이 글에서도 나와있는 것이지만 빌드 속도 문제를 떠나서도
최대한 multidex 를 사용하는 상황을 만들지 않는 것이 좋다. 그리고 나는 proguard를 항상 켜둔 상태도 개발을 하는 편이다.
프로젝트 막판에 proguard를 적용하게되면 proguard로 인한 여러가지 문제를 만날 수 있기 때문에 충돌을 미리 발견하기
위해서다. 하지만 이렇게하다보면 빌드 속도가 너무 떨어진다. 그래서 켰다가 껐다가 하긴하는데 너무 귀찮다.
그럼 본격적으로 설정을 시작해보자.
1. gradle.properties 파일을 변경
프로젝트 Root에 있는 gradle.properties을 편집한다. 기존에 파일이 없다면 추가한다.
여기에는 gradle 빌드 할 때 인수를 설정할 수 있다. 한가지 더 알려주자면 프로젝트별로 설정하는 것 외에도
모든 프로젝트에 설정을 추가할 수도 있다. 해당 파일의 경로는 OSX 기준으로 ~/.gradle/gradle.properties
이다.
윈도우나 리눅스도 비슷한 경로에 있을 것으로 생각된다. (없다면 추가해도 된다).
gradle.properties
위 설정에 대한 간략한 설명은 아래와 같다.
- org.gradle.daemon
: 데몬 프로세스를 사용할지 여부 설정한다.
true 설정시 gradle을 daemon 모드로 실행하여 빌드시 gradle을 다시 실행하는 시간을 줄여준다. - org.gradle.jvmargs
: 실행시 JVM 인수로 메모리를 설정을 늘려 메모리 부족으로 인한 속도저하를 막는 것이 목적이다.
따라서 적절한 양의 메모리를 할당해 주면 된다. - org.gradle.parallel
: gradle 병렬 빌드 모드를 설정한다.
여러 프로젝트를 빌드 할 때 효과가 있다. - org.gradle.configureondemand
: 관련 프로젝트가 있다면 필요한 부분만 빌드 설정한다.
크게 성능이 향상되는 것 같지는 않지만 조금의 성능 향상은 있는 것 같다.
사실 다음에 소개할 gradle 버전 업이 훨씬 체감 성능 향상에 도움을 준다.
2. Android Studio 1.3 / Gradle 2.4 이상 사용
Android Studio 1.3 / Gradle 2.4 이상으로 버전업되면서 대폭 성능 향상이 있었다.
실제로 나의 경우엔 상당한 속도 향상이 있었다. 그래도 proguard를 적용하게되면 느리긴 마찬가지긴 하다.
구글의 설명을 보려면 Google I/O 2015 - What’s New in Android Development Tools을 참고하면 된다.
단, 주의할 것은 Android Studio 1.3 이상을 사용한다고 Gradle 2.4 이상을 무조건 사용하는 것은 아니라는 것이다.
신규 프로젝트가 아니어서 그런지 나의 프로젝트에서는 2.2.1을 그대로 사용하고 있었다.
(File > Project Structure > Project > Gradle version에서 2.4로 변경함으로써 적용할 수 있다).
3. gradle를 오프라인 모드로 변경
다른 사람들은 이 방법이 아주 효과적이었다고 하는데 나의 경우는 크게 차이가 나지 않았다.
(proguard로 인한 속도 저하라서 이 방법에 큰 도움이 되지 않았던 것 같다).
어쨌든 이 설정을 적용하면 gradle에서 매번 최신 버전을 확인하러가는 것을 생략 해 준다.
단, 신규 dependency를 추가하거나 변경하는 경우는 이 설정을 해제해야 한다.
약간은 귀찮을 수 있지만 dependency 변경은 크게 자주 발생하는 경우는 아니므로 문제되지 않을 것으로 생각된다.
Android Studio> Preferences> Gradle 의 Offline work에 체크.
4. jcenter Maven Repository 사용
jcenter와 Maven Central은 모두 Java / Android 라이브러리들을 배포한다. 초기 안드로이드 스튜디오에서 프로젝트를
생성하면 기본적으로 Maven Central를 사용(repositories { mavenCentral() }
)하도록 세팅되었다.
하지만 이제는 안드로이드 스튜디오에서 프로젝트를 생성하면 jcenter가 사용(repositories { jcenter() }
)되도록 세팅된다.
이 부분이 변경된 이유는 여러가지가 있다고 하지만 그중에서 빌드 속도에 영향을 줄 수 있는 부분이 있다.
jcenter는 CDN을 통해 라이브러리를 배포하기 때문에 Maven Central에 비해 빠르다는 것이다.
자세한 내용은 Android Studio – Migration from Maven Central to JCenter를 참고하자.
5. Speeding up Gradle builds
Speeding up Gradle builds에서는 몇가지 방법을 더 안내하고 있다. 간략하게 요약하면 아래와 같다.
(위의 설명들과 유사한 부분도 많다). 상세한 설명은 위 링크를 참조하기 바란다.
Maven Central vs. JCenter
mavenCentral() 대신 jcenter()를 사용해라.
Get the latest version of Gradle
최신 버전의 Gradle을 사용하라.
Gradle properties
아래의 Gradle properties를 적용하라(위의 설명이 더 상세하다).
How to use Gradle properties
Gradle properties를 프로젝트별로 설정하기보다 전역으로 설정하라.
다중 모듈 빌드
다중 모뮬을 사용하는 경우에 속도 향상 방법이 안내되어 있으니 필요한 경우에 원본글에 가서 참조 바란다.
안드로이드 스튜디오 빌드 속도 향상 시키기
프로젝트의 루트에 gradle.properties를 생성하고 안드로이드 스튜디오를 재실행하면 반영이 됩니다.
마지막 라인이 중요해요
project.android.dexOptions.preDexLibraries = false
# Project-wide Gradle settings.
# IDE (eg Android Studio) users :
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http : // www.gradle.org/docs/current/userguide/build_environment.html
# The Gradle daemon aims to improve the startup and execution time of Gradle.
# When set to true the Gradle daemon is to run the build.
# TODO : disable daemon on CI, Since Builds should BE clean and Reliable on servers
org.gradle.daemon = true
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value : -Xmx10248m -XX : MaxPermSize = 256M
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should on ly be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec : decoupled_projects
org.gradle.parallel = true
# Enables new incubating mode that makes Gradle selective when configuring projects.
# on ly relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html #sec : configuration_on_demand
org.gradle.configureondemand = true
project.android.dexOptions.preDexLibraries = false
Android Studio 속도 향상 스크립트
[build.Gradle]
defaultConfig {
applicationId ; dfsdfdsf
minSdkVersion 21 // 21이상으로 하면 빨라집니다 (art모드로만 컴파일해서)
targetSdkVersion 22
versionCode 1
versionName “1.0”
multiDexEnabled true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
}
dexOptions {
jumboMode = true
javaMaxHeapSize “4g”
incremental true
}
[Gradle.properties]
org.gradle.daemon=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.configureondemand=true
Speed up your build in Android Studio
Gradle provides a lot of flexibility, but this power comes at the cost of a slower build process. Android Studio is based on Gradle.
When we are working with Android Studio, as our project is getting bigger and bigger, our daily / development build is getting slower and slower.
For example, one of our project need more than 40s to complete build once after we modified the Java code. If we build 100 times per day, the build process will take nearly an hour. Image that we can do nothing but only wait in an hour, that is really a waste of time.
Today we will try to make the build a little faster.
There are some solution we can find easily by a simple search:
org.gradle.daemon = true
org.gradle.parallel = true
make gradle work in
offline work
modeset up large vm heap size: 2G
But all of them can not bring significant speeding up, the build tool in Android Studio has already done most these work.
Profile
If you want to figure out the cause, you can try profiling your build process.
You can add the --profile
flag to any Gradle task. Adding this flag will create a report under build/reports/profile
.
It looks like:
Here is an example.
To enable profile
in Android Studio, you must config the command line options like bellow:
Why it is so slow
After we inspect the profile again and again, we can figure out some reasons that make build process slow:
some long running tasks
multiDexEnabled
too much dependencies
Solutions
1. Disable long running task
We can disable some long running tasks in dev mode.
tasks.whenTaskAdded { task ->
if (task.name.startsWith(":zxing:") || task.name.startsWith(":share-lib:")) {
task.enabled = false
}
}
2. Shrink the project
We can not really shrink the project unless we remove some functions of our APP.
But we can shrink our project in dev mode. We can disable some module, here is the structure of our project:
There are two grops of module:
share-lib
andshare-lib-no-op
zxing
andzxing-no-op
The
no-op
project is an empty module, we include this empty module in debug complie:debugCompile(project(':share-lib-no-op')) { } releaseCompile(project(':share-lib')) { } debugCompile(project(':zxing-no-op')) { } releaseCompile(project(':zxing')) { }
The code in
share-lib
do the real work:public class ShareProxyImpl { public void sendShare(ShareRequestDO request, Activity activity) { new ISShareController().startShare(activity, new ShareRequest(request)); } public void onActivityResult(Context context, int requestCode, int resultCode, Intent data) { ISShareController.onActivityResult(requestCode, resultCode, data); } }
And the code in
share-lib-no-op
does nothing:public class ShareProxyImpl { public void sendShare(ShareRequestDO request, Activity activity) { Toast.makeText(activity, "ShareProxyImpl:no-op:sendShare", Toast.LENGTH_SHORT).show(); } public void onActivityResult(Context context, int requestCode, int resultCode, Intent data) { Toast.makeText(context, "ShareProxyImpl:no-op:onActivityResult", Toast.LENGTH_SHORT).show(); } }
In this way, we can reduce a lot of dependence in debug complie.
Once the project is shrinked, we do not need multiDexEnabled
in debug mode.
This is the profile before we adjust our project:
And this is the current profile:
We only need about 15 seconds to finish a debug build, if we only modify the resource, that will be faster.
3. Jack and Jill
It is a experimental new Android tool chain, it may be faster in the future, for it can meger the dex file in a very fast way.
But currently(2015/07/28) it is very slow, the complie process take a very long time, it is nearly 2 minitues in our project.
'IT_Programming > Dev Tools' 카테고리의 다른 글
[GIT] git 실수로 한 commit, push 강제 취소 시키기 (0) | 2015.12.23 |
---|---|
안드로이드 스튜디오 cannot resolve symbol r :: 강력한 해결법 (0) | 2015.11.27 |
[펌][안드로이드 스튜디오] Android NDK Debugging / 네이티브 코드 디버깅하기 (0) | 2015.08.20 |
[안드로이드 스튜디오] apk 이름 변경 하기, 버전별 자동 생성 정리하기 (0) | 2015.08.17 |
[펌] Atlassian JIRA를 이용한 애자일 Scrum 프로젝트 관리 (0) | 2015.07.20 |