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

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

ตั้งแต่ Android 14 เป็นต้นไป การคอมไพล์ AOT ในอุปกรณ์สำหรับแอป (หรือที่เรียกว่า dexopt) จะจัดการโดยบริการ ART บริการ 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 (ค่าเริ่มต้น: ความเร็ว)

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

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

สำหรับแอปดังกล่าว หากมีการขอการคอมไพล์ตามคำแนะนำโปรไฟล์ บริการ ART จะพยายามใช้โปรไฟล์ระบบคลาวด์ก่อน หากไม่มีโปรไฟล์ระบบคลาวด์อยู่ บริการ ART จะกลับไปใช้ตัวกรองคอมไพเลอร์ที่ระบุโดย 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 ในเบื้องหลัง บริการ 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 กําหนดเวลางาน bg.dexopt

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

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

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

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

ART Service API

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

ArtManagerLocal เป็นซิงเกิลตันของ 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());
}

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

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();

นอกจากนี้ คุณยังยกเลิกการจัดระเบียบ Dex ในเบื้องหลังซึ่งบริการ ART เป็นผู้เริ่มได้ด้วย

getArtManagerLocal().cancelBackgroundDexoptJob();

ดูผลลัพธ์ของ dexopt

หากการดําเนินการเริ่มต้นด้วยการเรียกใช้ dexoptPackage คุณจะดูผลลัพธ์ได้จากค่าที่แสดงผล

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

// Process the result here.
...

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

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

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

อาร์กิวเมนต์ที่ 2 คือผู้ดำเนินการของคอลแบ็ก หากต้องการเรียกใช้การเรียกกลับในเธรดเดียวกับที่ดำเนินการ dexopt ให้ใช้ 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 ได้อย่างมีประสิทธิภาพ

หากการดำเนินการที่คุณยกเลิกคือการแยกไฟล์ Dex เบื้องหลัง ระบบจะดำเนินการตามนโยบายการลองอีกครั้งเริ่มต้น (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 เมื่อติดตั้งแอป ให้ป้องกันไม่ให้เครื่องมือจัดการแพ็กเกจเรียกใช้ dexoptPackage

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

คุณสามารถลบล้างตัวกรองคอมไพเลอร์สำหรับบางแพ็กเกจได้โดยลงทะเบียนการเรียกกลับผ่าน setAdjustCompilerFilterCallback ระบบจะเรียกใช้การเรียกกลับทุกครั้งที่มีการเปลี่ยนรูปแบบแพ็กเกจ ไม่ว่าจะเริ่มต้นการเปลี่ยนรูปแบบโดยบริการ ART ระหว่างการบูตและการเปลี่ยนรูปแบบในเบื้องหลัง หรือโดยการเรียก 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 พื้นหลัง

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

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

งาน 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

หากต้องการใช้โปรไฟล์เพื่อแนะนำ dexopt ให้วางไฟล์ .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 Service สามารถใช้ได้ บรรทัดที่สองจะเรียกใช้ 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)