การกําหนดค่าบริการ ART

ก่อนเริ่มต้น โปรดดูภาพรวมระดับสูงของบริการ ART

ตั้งแต่ Android 14 เป็นต้นไป บริการ ART จะจัดการการคอมไพล์ AOT ในอุปกรณ์สำหรับ แอป (หรือที่เรียกว่า dexopt) บริการ ART เป็นส่วนหนึ่งของโมดูล ART และคุณปรับแต่งได้ผ่านพร็อพเพอร์ตี้ของระบบและ API

พร็อพเพอร์ตี้ของระบบ

บริการ ART รองรับตัวเลือก dex2oat ที่เกี่ยวข้องทั้งหมด

นอกจากนี้ บริการ ART ยังรองรับพร็อพเพอร์ตี้ของระบบต่อไปนี้ด้วย

pm.dexopt.<reason>

ซึ่งเป็นชุดพร็อพเพอร์ตี้ของระบบที่กำหนดตัวกรองคอมไพเลอร์เริ่มต้น สำหรับเหตุผลในการคอมไพล์ที่กำหนดไว้ล่วงหน้าทั้งหมดซึ่งอธิบายไว้ในสถานการณ์ Dexopt

ดูข้อมูลเพิ่มเติมได้ที่ ตัวกรองคอมไพเลอร์

ค่าเริ่มต้นมาตรฐานมีดังนี้

pm.dexopt.first-boot=verify
pm.dexopt.boot-after-ota=verify
pm.dexopt.boot-after-mainline-update=verify
pm.dexopt.bg-dexopt=speed-profile
pm.dexopt.inactive=verify
pm.dexopt.cmdline=verify

pm.dexopt.shared (ค่าเริ่มต้น: speed)

นี่คือตัวกรองคอมไพเลอร์สำรองสำหรับแอปที่แอปอื่นๆ ใช้

โดยหลักการแล้ว บริการ ART จะทำการคอมไพล์ที่แนะนำโดยโปรไฟล์ (speed-profile) สำหรับ แอปทั้งหมดเมื่อเป็นไปได้ ซึ่งมักจะเกิดขึ้นระหว่าง dexopt ที่ทำงานอยู่เบื้องหลัง อย่างไรก็ตาม มี บางแอปที่แอปอื่นๆ ใช้ (ไม่ว่าจะผ่าน <uses-library> หรือโหลด แบบไดนามิกโดยใช้ Context#createPackageContext กับ CONTEXT_INCLUDE_CODE) แอปดังกล่าวไม่สามารถใช้โปรไฟล์ในเครื่อง ได้เนื่องด้วยเหตุผลด้านความเป็นส่วนตัว

สำหรับแอปดังกล่าว หากมีการขอการคอมไพล์ที่แนะนำโดยโปรไฟล์ บริการ ART จะพยายามใช้โปรไฟล์ในระบบคลาวด์ก่อน หากไม่มีโปรไฟล์ระบบคลาวด์ ART Service จะกลับไปใช้ตัวกรองคอมไพเลอร์ที่ระบุโดย pm.dexopt.shared

หากการคอมไพล์ที่ขอไม่ได้ใช้การเพิ่มประสิทธิภาพตามโปรไฟล์ พร็อพเพอร์ตี้นี้จะไม่มีผล

pm.dexopt.<reason>.concurrency (ค่าเริ่มต้น: 1)

นี่คือจำนวนการเรียกใช้ dex2oat สำหรับเหตุผลในการคอมไพล์ที่กำหนดไว้ล่วงหน้าบางอย่าง (first-boot, boot-after-ota, boot-after-mainline-update และ bg-dexopt)

โปรดทราบว่าผลลัพธ์ของตัวเลือกนี้จะรวมกับ ตัวเลือกการใช้ทรัพยากร dex2oat (dalvik.vm.*dex2oat-threads, dalvik.vm.*dex2oat-cpu-set และโปรไฟล์งาน)

  • dalvik.vm.*dex2oat-threads ควบคุมจำนวนเธรดสำหรับการเรียกใช้ dex2oat แต่ละครั้ง ส่วน pm.dexopt.<reason>.concurrency ควบคุมจำนวนการเรียกใช้ dex2oat กล่าวคือ จำนวนเธรดพร้อมกันสูงสุดคือ ผลคูณของพร็อพเพอร์ตี้ระบบทั้ง 2 รายการ
  • dalvik.vm.*dex2oat-cpu-set และโปรไฟล์งานจะจำกัดการใช้งานคอร์ CPU เสมอ ไม่ว่าจำนวนสูงสุดของเธรดพร้อมกันจะเป็นเท่าใดก็ตาม (กล่าวถึง ข้างต้น)

การเรียกใช้ dex2oat ครั้งเดียวอาจใช้แกน CPU ทั้งหมดไม่เต็มที่ ไม่ว่าdalvik.vm.*dex2oat-threadsจะเปิดอยู่หรือไม่ก็ตาม ดังนั้น การเพิ่มจำนวนการเรียกใช้ dex2oat (pm.dexopt.<reason>.concurrency) จะช่วยให้ใช้แกน CPU ได้ดีขึ้นเพื่อ เร่งความคืบหน้าโดยรวมของ dexopt ซึ่งจะมีประโยชน์อย่างยิ่งในระหว่าง การบูต

อย่างไรก็ตาม การเรียกใช้ dex2oat มากเกินไปอาจทำให้อุปกรณ์มีหน่วยความจำไม่เพียงพอ แม้ว่าปัญหานี้จะลดลงได้โดยการตั้งค่า dalvik.vm.dex2oat-swap เป็น true เพื่ออนุญาตให้ใช้ไฟล์สวอป การเรียกใช้มากเกินไปอาจทำให้เกิด การสลับบริบทที่ไม่จำเป็นด้วย ดังนั้น คุณควรปรับตัวเลขนี้อย่างระมัดระวัง โดยพิจารณาจากผลิตภัณฑ์แต่ละรายการ

pm.dexopt.downgrade_after_inactive_days (ค่าเริ่มต้น: ไม่ได้ตั้งค่า)

หากตั้งค่าตัวเลือกนี้ไว้ บริการ ART จะ dexopt เฉพาะแอปที่ใช้ภายในจำนวนวันที่ที่ระบุล่าสุด

นอกจากนี้ หากพื้นที่เก็บข้อมูลเหลือน้อยมาก ในระหว่างการเพิ่มประสิทธิภาพ DEX ในเบื้องหลัง บริการ ART จะลดระดับตัวกรองคอมไพเลอร์ของแอปที่ไม่ได้ใช้ในช่วงระยะเวลาที่กำหนดล่าสุดเพื่อเพิ่มพื้นที่ว่าง เหตุผลของคอมไพเลอร์สำหรับเรื่องนี้คือ inactive และตัวกรองคอมไพเลอร์จะกำหนดโดย pm.dexopt.inactive เกณฑ์พื้นที่ ที่จะทริกเกอร์ฟีเจอร์นี้คือเกณฑ์พื้นที่เหลือน้อยของเครื่องมือจัดการพื้นที่เก็บข้อมูล (กำหนดค่าได้ผ่านการตั้งค่าส่วนกลาง sys_storage_threshold_percentage และ sys_storage_threshold_max_bytes ค่าเริ่มต้น: 500 MB) บวก 500 MB

หากคุณปรับแต่งรายการแพ็กเกจผ่าน ArtManagerLocal#setBatchDexoptStartCallback ระบบจะไม่ลดรุ่นแพ็กเกจในรายการที่ BatchDexoptStartCallback จัดหาให้สำหรับ bg-dexopt

pm.dexopt.disable_bg_dexopt (ค่าเริ่มต้น: false)

ใช้สำหรับการทดสอบเท่านั้น ซึ่งจะป้องกันไม่ให้บริการ ART กำหนดเวลางาน dexopt ที่ทำงานอยู่เบื้องหลัง

หากมีการตั้งค่างาน dexopt ในเบื้องหลังไว้แล้วแต่ยังไม่ได้เรียกใช้ ตัวเลือกนี้จะไม่มีผล กล่าวคือ งานจะยังคงทำงานต่อไป

ลำดับคำสั่งที่แนะนำเพื่อป้องกันไม่ให้งาน dexopt ในเบื้องหลังทำงานมีดังนี้

setprop pm.dexopt.disable_bg_dexopt true
pm bg-dexopt-job --disable

บรรทัดแรกจะป้องกันไม่ให้กำหนดเวลางาน dexopt ในเบื้องหลัง หากยังไม่ได้กำหนดเวลา บรรทัดที่ 2 จะยกเลิกการกำหนดเวลางาน dexopt ในเบื้องหลัง หากมีการกำหนดเวลาไว้แล้ว และจะยกเลิกงาน dexopt ในเบื้องหลังทันทีหากกำลังทำงานอยู่

API ของบริการ ART

บริการ ART เปิดเผย Java API เพื่อการปรับแต่ง API กำหนดไว้ใน ArtManagerLocal ดู Javadoc ใน art/libartservice/service/java/com/android/server/art/ArtManagerLocal.java สำหรับ การใช้งาน (แหล่งที่มาของ Android 14, แหล่งที่มาของการพัฒนาที่ยังไม่ได้เผยแพร่)

ArtManagerLocal เป็น Singleton ที่ LocalManagerRegistry ถือครอง ฟังก์ชันตัวช่วย com.android.server.pm.DexOptHelper#getArtManagerLocal จะช่วยให้คุณ ได้รับ

import static com.android.server.pm.DexOptHelper.getArtManagerLocal;

API ส่วนใหญ่ต้องมีอินสแตนซ์ของ PackageManagerLocal.FilteredSnapshot ซึ่งมีข้อมูลของแอปทั้งหมด คุณรับได้โดยการเรียกใช้ PackageManagerLocal#withFilteredSnapshot ซึ่ง PackageManagerLocal ยังเป็น ออบเจ็กต์เดียวที่ LocalManagerRegistry ถือครองอยู่และรับได้จาก com.android.server.pm.PackageManagerServiceUtils#getPackageManagerLocal

import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal;

กรณีการใช้งาน API ทั่วไปบางส่วนมีดังนี้

ทริกเกอร์ dexopt สำหรับแอป

คุณทริกเกอร์ dexopt สำหรับแอปใดก็ได้ทุกเมื่อโดยเรียกใช้ ArtManagerLocal#dexoptPackage

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build());
}

นอกจากนี้ คุณยังส่งเหตุผลในการเพิ่มประสิทธิภาพ DEX ของคุณเองได้ด้วย หากทำเช่นนั้น คุณต้องตั้งค่าคลาสลำดับความสำคัญและตัวกรองคอมไพเลอร์อย่างชัดเจน

try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  getArtManagerLocal().dexoptPackage(
      snapshot,
      "com.google.android.calculator",
      new DexoptParams.Builder("my-reason")
          .setCompilerFilter("speed-profile")
          .setPriorityClass(ArtFlags.PRIORITY_BACKGROUND)
          .build());
}

ยกเลิก dexopt

หากการดำเนินการเริ่มต้นด้วยdexoptPackageการโทร คุณจะส่งสัญญาณการยกเลิกได้ ซึ่งจะช่วยให้คุณยกเลิกการดำเนินการได้ในบางจุด ซึ่งอาจมีประโยชน์เมื่อคุณเรียกใช้ dexopt แบบไม่พร้อมกัน

Executor executor = ...;  // Your asynchronous executor here.
var cancellationSignal = new CancellationSignal();
executor.execute(() -> {
  try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
    getArtManagerLocal().dexoptPackage(
        snapshot,
        "com.google.android.calculator",
        new DexoptParams.Builder(ReasonMapping.REASON_INSTALL).build(),
        cancellationSignal);
  }
});

// When you want to cancel the operation.
cancellationSignal.cancel();

นอกจากนี้ คุณยังยกเลิก dexopt ในเบื้องหลังที่บริการ ART เริ่มต้นได้ด้วย

getArtManagerLocal().cancelBackgroundDexoptJob();

รับผลลัพธ์ dexopt

หากการดำเนินการเริ่มต้นด้วยการเรียก dexoptPackage คุณจะรับผลลัพธ์ได้ จากค่าที่ส่งคืน

DexoptResult result;
try (var snapshot = getPackageManagerLocal().withFilteredSnapshot()) {
  result = getArtManagerLocal().dexoptPackage(...);
}

// Process the result here.
...

นอกจากนี้ บริการ ART ยังเริ่มการดำเนินการ dexopt ด้วยตัวเองในหลายสถานการณ์ เช่น dexopt ในเบื้องหลัง หากต้องการฟังผลลัพธ์ dexopt ทั้งหมด ไม่ว่าการดำเนินการจะเริ่มต้นโดยการเรียก dexoptPackage หรือโดยบริการ ART ให้ใช้ ArtManagerLocal#addDexoptDoneCallback

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */,
    Runnable::run,
    (result) -> {
      // Process the result here.
      ...
    });

อาร์กิวเมนต์แรกจะกำหนดว่าจะรวมเฉพาะการอัปเดตในผลลัพธ์หรือไม่ หากต้องการฟังเฉพาะแพ็กเกจที่ dexopt อัปเดต ให้ตั้งค่าเป็น true

อาร์กิวเมนต์ที่ 2 คือตัวดำเนินการของโค้ดเรียกกลับ หากต้องการเรียกใช้การเรียกกลับในเธรดเดียวกันกับที่ทำการเพิ่มประสิทธิภาพ DEX ให้ใช้ Runnable::run หากไม่ต้องการให้ การเรียกกลับบล็อก dexopt ให้ใช้ตัวดำเนินการแบบไม่พร้อมกัน

คุณเพิ่มการเรียกกลับได้หลายรายการ และบริการ ART จะดำเนินการทั้งหมด ตามลำดับ การโทรกลับทั้งหมดจะยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะนำออก

หากต้องการนำการเรียกกลับออก ให้เก็บข้อมูลอ้างอิงของการเรียกกลับเมื่อคุณ เพิ่มการเรียกกลับ และใช้ ArtManagerLocal#removeDexoptDoneCallback

DexoptDoneCallback callback = (result) -> {
  // Process the result here.
  ...
};

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */, Runnable::run, callback);

// When you want to remove it.
getArtManagerLocal().removeDexoptDoneCallback(callback);

ปรับแต่งรายการแพ็กเกจและพารามิเตอร์ dexopt

บริการ ART จะเริ่มการดำเนินการ dexopt ด้วยตัวเองในระหว่างการบูตและ dexopt ที่ทำงานอยู่เบื้องหลัง หากต้องการปรับแต่งรายการแพ็กเกจหรือพารามิเตอร์ dexopt สำหรับการดำเนินการเหล่านั้น ให้ใช้ ArtManagerLocal#setBatchDexoptStartCallback

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      switch (reason) {
        case ReasonMapping.REASON_BG_DEXOPT:
          var myPackages = new ArrayList<String>(defaultPackages);
          myPackages.add(...);
          myPackages.remove(...);
          myPackages.sort(...);
          builder.setPackages(myPackages);
          break;
        default:
          // Ignore unknown reasons.
      }
    });

คุณสามารถเพิ่มรายการลงในรายการแพ็กเกจ นำรายการออกจากรายการ จัดเรียงรายการ หรือแม้แต่ ใช้รายการอื่นที่แตกต่างกันโดยสิ้นเชิง

การเรียกกลับต้องไม่สนใจเหตุผลที่ไม่รู้จักเนื่องจากอาจมีการเพิ่มเหตุผลเพิ่มเติมในอนาคต

คุณตั้งค่า BatchDexoptStartCallback ได้สูงสุด 1 รายการ การโทรกลับจะยังคง ใช้งานได้สำหรับการโทรทั้งหมดในอนาคตจนกว่าคุณจะล้าง

หากต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearBatchDexoptStartCallback

getArtManagerLocal().clearBatchDexoptStartCallback();

ปรับแต่งพารามิเตอร์ของงาน dexopt ในเบื้องหลัง

โดยค่าเริ่มต้น งาน dexopt ในเบื้องหลังจะทำงานวันละครั้งเมื่ออุปกรณ์ไม่ได้ใช้งาน และกำลังชาร์จ ซึ่งเปลี่ยนแปลงได้โดยใช้ ArtManagerLocal#setScheduleBackgroundDexoptJobCallback

getArtManagerLocal().setScheduleBackgroundDexoptJobCallback(
    Runnable::run,
    builder -> {
      builder.setPeriodic(TimeUnit.DAYS.toMillis(2));
    });
นโยบายการลองใหม่นี้ได้เนื่องจากข้อจำกัดของ API ตัวจัดกำหนดเวลางาน

คุณตั้งค่า ScheduleBackgroundDexoptJobCallback ได้สูงสุด 1 รายการ การโทรกลับจะ ยังคงใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะล้างการโทรกลับ

หากต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearScheduleBackgroundDexoptJobCallback

getArtManagerLocal().clearScheduleBackgroundDexoptJobCallback();

ปิดใช้ dexopt ชั่วคราว

การดำเนินการ dexopt ใดๆ ที่เริ่มต้นโดยบริการ ART จะทริกเกอร์ BatchDexoptStartCallback คุณยกเลิกการดำเนินการต่อไปได้เพื่อ ปิดใช้ dexopt อย่างมีประสิทธิภาพ

หากการดำเนินการที่คุณยกเลิกคือ dexopt ในเบื้องหลัง การดำเนินการจะใช้นโยบายการลองใหม่เริ่มต้น (30 วินาที แบบทวีคูณ โดยจำกัดไว้ที่ 5 ชั่วโมง)

// Good example.

var shouldDisableDexopt = new AtomicBoolean(false);

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      if (shouldDisableDexopt.get()) {
        cancellationSignal.cancel();
      }
    });

// Disable dexopt.
shouldDisableDexopt.set(true);
getArtManagerLocal().cancelBackgroundDexoptJob();

// Re-enable dexopt.
shouldDisableDexopt.set(false);

คุณมี BatchDexoptStartCallback ได้สูงสุด 1 รายการ หากต้องการใช้ BatchDexoptStartCallback เพื่อปรับแต่งรายการแพ็กเกจหรือพารามิเตอร์ dexopt ด้วย คุณต้องรวมโค้ดไว้ในการเรียกกลับรายการเดียว

// Bad example.

// Disable dexopt.
getArtManagerLocal().unscheduleBackgroundDexoptJob();

// Re-enable dexopt.
getArtManagerLocal().scheduleBackgroundDexoptJob();

การดำเนินการ dexopt ที่ดำเนินการในการติดตั้งแอปไม่ได้เริ่มต้นโดย ART Service แต่จะเริ่มต้นโดยตัวจัดการแพ็กเกจผ่านการเรียกใช้ dexoptPackage ดังนั้นจึงไม่ทริกเกอร์ BatchDexoptStartCallback หากต้องการปิดใช้ dexopt เมื่อติดตั้งแอป ให้ป้องกันไม่ให้ Package Manager เรียกใช้ dexoptPackage

ลบล้างตัวกรองคอมไพเลอร์สำหรับบางแพ็กเกจ (Android 15 ขึ้นไป)

คุณลบล้างตัวกรองคอมไพเลอร์สำหรับแพ็กเกจบางรายการได้โดยการลงทะเบียน การเรียกกลับผ่าน setAdjustCompilerFilterCallback ระบบจะเรียกใช้การเรียกกลับ เมื่อใดก็ตามที่จะมีการทำ Dexopt แพ็กเกจ ไม่ว่าการทำ Dexopt จะเริ่มต้นโดย บริการ ART ระหว่างการบูตและการทำ Dexopt เบื้องหลัง หรือโดยการเรียกใช้ dexoptPackage API

หากไม่จำเป็นต้องปรับแพ็กเกจ คอลแบ็กต้องแสดงผล originalCompilerFilter

getArtManagerLocal().setAdjustCompilerFilterCallback(
    Runnable::run,
    (packageName, originalCompilerFilter, reason) -> {
      if (isVeryImportantPackage(packageName)) {
        return "speed-profile";
      }
      return originalCompilerFilter;
    });

คุณตั้งค่า AdjustCompilerFilterCallback ได้เพียงรายการเดียว หากต้องการใช้ AdjustCompilerFilterCallbackเพื่อลบล้างตัวกรองคอมไพเลอร์สำหรับแพ็กเกจหลายรายการ คุณต้องรวมโค้ดไว้ในการเรียกกลับรายการเดียว การโทรกลับจะยังคง ใช้งานได้สำหรับการโทรในอนาคตทั้งหมด เว้นแต่คุณจะล้าง

หากต้องการล้างการโทรกลับ ให้ใช้ ArtManagerLocal#clearAdjustCompilerFilterCallback

getArtManagerLocal().clearAdjustCompilerFilterCallback();

การปรับแต่งอื่นๆ

นอกจากนี้ บริการ ART ยังรองรับการปรับแต่งอื่นๆ อีกด้วย

ตั้งค่าเกณฑ์ความร้อนสำหรับ dexopt ในเบื้องหลัง

Job Scheduler จะควบคุมอุณหภูมิของงาน dexopt ในเบื้องหลัง ระบบจะยกเลิกงานทันทีเมื่ออุณหภูมิถึง THERMAL_STATUS_MODERATE คุณปรับเกณฑ์ของ THERMAL_STATUS_MODERATE ได้

ตรวจสอบว่า dexopt เบื้องหลังทำงานอยู่หรือไม่

Job Scheduler จะจัดการงาน dexopt ในแบ็กกราวด์ และรหัสงานคือ 27873780 หากต้องการตรวจสอบว่างานกำลังทำงานอยู่หรือไม่ ให้ใช้ Job Scheduler API

// Good example.

var jobScheduler =
    Objects.requireNonNull(mContext.getSystemService(JobScheduler.class));
int reason = jobScheduler.getPendingJobReason(27873780);

if (reason == PENDING_JOB_REASON_EXECUTING) {
  // Do something when the job is running.
  ...
}
// Bad example.

var backgroundDexoptRunning = new AtomicBoolean(false);

getArtManagerLocal().setBatchDexoptStartCallback(
    Runnable::run,
    (snapshot, reason, defaultPackages, builder, cancellationSignal) -> {
      if (reason.equals(ReasonMapping.REASON_BG_DEXOPT)) {
        backgroundDexoptRunning.set(true);
      }
    });

getArtManagerLocal().addDexoptDoneCallback(
    false /* onlyIncludeUpdates */,
    Runnable::run,
    (result) -> {
      if (result.getReason().equals(ReasonMapping.REASON_BG_DEXOPT)) {
        backgroundDexoptRunning.set(false);
      }
    });

if (backgroundDexoptRunning.get()) {
  // Do something when the job is running.
  ...
}

ระบุโปรไฟล์สำหรับ dexopt

หากต้องการใช้โปรไฟล์เพื่อเป็นแนวทางในการเพิ่มประสิทธิภาพ DEX ให้วางไฟล์ .prof หรือไฟล์ .dm ไว้ข้าง APK

ไฟล์ .prof ต้องเป็นไฟล์โปรไฟล์รูปแบบไบนารี และชื่อไฟล์ต้องเป็นชื่อไฟล์ของ APK + .prof ตัวอย่างเช่น

base.apk.prof

ชื่อไฟล์ของไฟล์ .dm ต้องเป็นชื่อไฟล์ของ APK โดยเปลี่ยนนามสกุลเป็น .dm ตัวอย่างเช่น

base.dm

หากต้องการยืนยันว่ามีการใช้โปรไฟล์สำหรับ dexopt ให้เรียกใช้ dexopt ด้วย speed-profile แล้วตรวจสอบผลลัพธ์

pm art clear-app-profiles <package-name>
pm compile -m speed-profile -f -v <package-name>

บรรทัดแรกจะล้างโปรไฟล์ทั้งหมดที่รันไทม์สร้างขึ้น (เช่น โปรไฟล์ใน /data/misc/profiles) หากมี เพื่อให้แน่ใจว่าโปรไฟล์ที่อยู่ข้าง APK เป็น โปรไฟล์เดียวที่บริการ ART อาจใช้ได้ บรรทัดที่ 2 เรียกใช้ dexopt ด้วย speed-profile และส่ง -v เพื่อพิมพ์ผลลัพธ์แบบละเอียด

หากมีการใช้โปรไฟล์ คุณจะเห็น actualCompilerFilter=speed-profile ในผลการค้นหา หรือไม่เช่นนั้น คุณจะเห็น actualCompilerFilter=verify ตัวอย่างเช่น

DexContainerFileDexoptResult{dexContainerFile=/data/app/~~QR0fTV0UbDbIP1Su7XzyPg==/com.google.android.gms-LvusF2uARKOtBbcaPHdUtQ==/base.apk, primaryAbi=true, abi=x86_64, actualCompilerFilter=speed-profile, status=PERFORMED, dex2oatWallTimeMillis=4549, dex2oatCpuTimeMillis=14550, sizeBytes=3715344, sizeBeforeBytes=3715344}

สาเหตุทั่วไปที่ทำให้บริการ ART ไม่ใช้โปรไฟล์มีดังนี้

  • โปรไฟล์มีชื่อไฟล์ไม่ถูกต้องหรือไม่ได้อยู่ข้าง APK
  • โปรไฟล์อยู่ในรูปแบบที่ไม่ถูกต้อง
  • โปรไฟล์ไม่ตรงกับ APK (Checksum ในโปรไฟล์ไม่ตรงกับ Checksum ของไฟล์ .dex ใน APK)