LoginSignup
39
40

More than 5 years have passed since last update.

Androidアプリのビルドを高速化するDex In Processが有効になる条件

Last updated at Posted at 2016-07-28

きっかけ

Androidの実行ファイルにコンパイルするDexをプロセス内で行うことにより、Androidアプリのビルドを高速化するDexInProcessですが、いつ有効になったりならなかったりするのかがよくわかりません。(詳しい仕組みはわかっていません)
詳しい判定をちょっとソース見たら分かりそうじゃないかなと思って見てみました。

まとめ

  • Android Gradle Pluginを2.1.2以上を使っている(この仕様になったのがどのバージョンからなのかは調べられていません) 設定場所:プロジェクト/build.gradleで設定
  • Build Tools Versionが23.0.2以上 設定場所:プロジェクト/app/build.gradleで設定
  • 自分でdexInProcess falseにしていない

./gradlew clean asseDebなどでビルドして以下のような警告文が出なければ有効になっている

Running dex as a separate process.

To run dex in process, the Gradle daemon needs a larger heap.
It currently has 520 MB.
For faster builds, increase the maximum heap size for the Gradle daemon to at least 1536 MB.
To do this set org.gradle.jvmargs=-Xmx1536M in the project gradle.properties.
For more information see https://docs.gradle.org/current/userguide/build_environment.html

また警告文が出た場合は、このTo do this set org.gradle.jvmargs=-Xmx1536M in the project gradle.properties.に従って、

プロジェクト/gradle.propertiesに

org.gradle.jvmargs=-Xmx1536M

を書けばOK(状況によって違うようなので1536Mの部分はコピペしないでください)

ただAndroid Gradle Plugin 2.1.2だと計算にバグがあり、javaMaxHeapSizeを設定していると、gradle.propertiesに記述しても有効にならない場合があるようです。Android Gradle Plugin 2.2で修正されているみたいです。
https://code.google.com/p/android/issues/detail?id=208214

読んでみた

ソースコードを読んでみたらshouldDexInProcessというメソッドで判定しているようです。
https://android.googlesource.com/platform/tools/base/+/028ba07/build-system/builder/src/main/java/com/android/builder/core/DexByteCodeConverter.java#250

    /**
     * Determine whether to dex in process.
     */
    @VisibleForTesting
    synchronized boolean shouldDexInProcess(
            @NonNull DexOptions dexOptions,
            @NonNull Revision buildToolsVersion) {

自分でgradleでdexInProcessを無効に設定していたらそっちを優先する(デフォルトは有効)

        if (!dexOptions.getDexInProcess()) {
            mIsDexInProcess = false;
            return false;
        }

Build Tools Versionが23.0.2未満だったら警告文出して無効にする

        if (buildToolsVersion.compareTo(DexProcessBuilder.FIXED_DX_MERGER) < 0) {
            // We substitute Dex > 23.0.2 with the local implementation.
            mLogger.warning("Running dex in-process requires build tools %1$s.\n"
                            + "For faster builds update this project to use the latest build tools.",
                    DexProcessBuilder.FIXED_DX_MERGER.toShortString());
            mIsDexInProcess = false;
            return false;
        }

ちなみにFIXED_DX_MERGERは以下のようになっている

ublic static final Revision FIXED_DX_MERGER = new Revision(23, 0, 2);

あとは自分が動いているVMの最大ヒープサイズ(gradle.propertiesのorg.gradle.jvmargsで設定)と Gradleで以下のように宣言できるjavaMaxHeapSizeを比較して、javaMaxHeapSize以上でないと警告文を出す感じです。
自分のプロセス内でビルドするので、その時にこのヒープサイズが必要になるということだと思いました。
ちなみにjavaMaxHeapSize '4g'しているとgradle.propertiesにorg.gradle.jvmargs=-Xmx4608Mを記述するように言われました。

    dexOptions {
        javaMaxHeapSize '4g'
    }

        // Requested memory for dex.
        long requestedHeapSize = parseHeapSize(dexOptions.getJavaMaxHeapSize(), mLogger);
        // Approximate heap size requested.
        long requiredHeapSizeHeuristic = requestedHeapSize + NON_DEX_HEAP_SIZE;
        // Get the approximate heap size that was specified by the user.
        // It is important that this be close to the -Xmx value specified, as is is compared with
        // the requiredHeapSizeHeuristic, which we suggest the user sets in their gradle.properties.
        long maxMemory = 0;
        for (MemoryPoolMXBean mpBean: ManagementFactory.getMemoryPoolMXBeans()) {
            if (mpBean.getType() == MemoryType.HEAP) {
                maxMemory += mpBean.getUsage().getMax();
            }
        }
        // Allow a little extra overhead (50M) as in practice the sum of the heap pools is
        // slightly lower than the Xmx setting specified by the user.
        final long EXTRA_HEAP_OVERHEAD =  50 * 1024 * 1024;
        if (requiredHeapSizeHeuristic > maxMemory + EXTRA_HEAP_OVERHEAD) {
            String dexOptionsComment = "";
            if (dexOptions.getJavaMaxHeapSize() != null) {
                dexOptionsComment = String.format(
                        " (based on the dexOptions.javaMaxHeapSize = %s)",
                        dexOptions.getJavaMaxHeapSize());
            }
            mLogger.warning("\nRunning dex as a separate process.\n\n"
                            + "To run dex in process, the Gradle daemon needs a larger heap.\n"
                            + "It currently has approximately %1$d MB.\n"
                            + "For faster builds, increase the maximum heap size for the "
                            + "Gradle daemon to more than %2$s MB%3$s.\n"
                            + "To do this set org.gradle.jvmargs=-Xmx%2$sM in the "
                            + "project gradle.properties.\n"
                            + "For more information see "
                            + "https://docs.gradle.org/current/userguide/build_environment.html\n",
                    maxMemory / (1024 * 1024),
                    requiredHeapSizeHeuristic / (1024 * 1024),
                    dexOptionsComment);
            mIsDexInProcess = false;
            return false;
        }
        mIsDexInProcess = true;
        return true;

39
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
40