การกําหนดค่าบริการ 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 (ค่าเริ่มต้น: speed)

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

โดยหลักการแล้ว บริการ 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 โดยค่าเริ่มต้นคือ 500MB) บวก 500MB

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

ART Service API

บริการ 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 ก็เป็น Singleton ที่ 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());
}

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

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 ยังเริ่มการดำเนินการ dexopt ด้วยตนเองในหลายสถานการณ์ เช่น dexopt ในเบื้องหลัง หากต้องการฟังผลลัพธ์ dexopt ทั้งหมด ไม่ว่าจะเริ่มต้นการดำเนินการโดยการเรียก dexoptPackage หรือโดยบริการ ART ให้ใช้ 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));
    });

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

ตั้งค่าเกณฑ์ความร้อนสำหรับการเพิ่มประสิทธิภาพ Dex ในเบื้องหลัง

ตัวจัดตารางงานจะควบคุมความร้อนของงาน 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)