Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db4a79a5 authored by Calin Juravle's avatar Calin Juravle
Browse files

Enable profile guided compilation on the framework side

The background compilation service will trigger a profile based
compilation instead of a full one. If no profile information is
available the compilation is skipped (see installd).

Note that the end decision whether or not to compile a package is taken
by dext2oat. We can't make the decision here because this service runs
under system server which cannot read app's profile data.

Bug: 26080105
Change-Id: I457ea8dea0557839c1f7cdc241770055732b0a4a
parent e53e428a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -4720,6 +4720,9 @@ public final class ActivityThread {
    }

    private static void setupJitProfileSupport(LoadedApk loadedApk, File cacheDir) {
        if (!SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
            return;
        }
        final ApplicationInfo appInfo = loadedApk.getApplicationInfo();
        if (isSharingRuntime(appInfo)) {
            // If sharing is enabled we do not have a unique application
+16 −5
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.net.LocalSocketAddress;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Slog;
import android.text.TextUtils;

import com.android.internal.util.Preconditions;

@@ -139,14 +140,24 @@ public class InstallerConnection {
    }

    public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
            int dexFlags) throws InstallerException {
        dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded, null /* outputPath */, dexFlags);
            int dexFlags, String volumeUuid, boolean useProfiles) throws InstallerException {
        dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded,
                null /*outputPath*/, dexFlags, volumeUuid, useProfiles);
    }

    public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
            int dexoptNeeded, String outputPath, int dexFlags) throws InstallerException {
        execute("dexopt", apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath,
                dexFlags);
            int dexoptNeeded, String outputPath, int dexFlags, String volumeUuid,
            boolean useProfiles) throws InstallerException {
        execute("dexopt",
                apkPath,
                uid,
                pkgName,
                instructionSet,
                dexoptNeeded,
                outputPath,
                dexFlags,
                volumeUuid,
                useProfiles ? '1' : '0');
    }

    private boolean connect() {
+4 −1
Original line number Diff line number Diff line
@@ -500,8 +500,11 @@ public class ZygoteInit {
                final int dexoptNeeded = DexFile.getDexOptNeeded(
                        classPathElement, "*", instructionSet, false /* defer */);
                if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                    // System server is fully AOTed and never profiled
                    // for profile guided compilation.
                    installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
                            dexoptNeeded, 0 /*dexFlags*/);
                            dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
                            false /*useProfiles*/);
                }
            }
        } catch (IOException | InstallerException e) {
+5 −0
Original line number Diff line number Diff line
@@ -586,6 +586,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
    char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];
    char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];
    char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];
    char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];
    char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
    char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
    char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
@@ -691,6 +692,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
    parseRuntimeOption("dalvik.vm.jitmaxsize", jitmaxsizeOptsBuf, "-Xjitmaxsize:");
    parseRuntimeOption("dalvik.vm.jitinitialsize", jitinitialsizeOptsBuf, "-Xjitinitialsize:");
    parseRuntimeOption("dalvik.vm.jitthreshold", jitthresholdOptsBuf, "-Xjitthreshold:");
    property_get("dalvik.vm.usejitprofiles", useJitProfilesOptsBuf, "");
    if (strcmp(useJitProfilesOptsBuf, "true") == 0) {
        addOption("-Xjitsaveprofilinginfo");
    }

    property_get("ro.config.low_ram", propBuf, "");
    if (strcmp(propBuf, "true") == 0) {
+11 −9
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.app.job.JobService;
import android.content.ComponentName;
import android.content.Context;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.util.ArraySet;
import android.util.Log;

@@ -50,12 +51,13 @@ public class BackgroundDexOptService extends JobService {

    final AtomicBoolean mIdleTime = new AtomicBoolean(false);

    public static void schedule(Context context, long minLatency) {
    private boolean useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);

    public static void schedule(Context context) {
        JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
                .setRequiresDeviceIdle(true)
                .setRequiresCharging(true)
                .setMinimumLatency(minLatency)
                .setPeriodic(TimeUnit.DAYS.toMillis(1))
                .build();
        js.schedule(job);
@@ -63,16 +65,17 @@ public class BackgroundDexOptService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        Log.i(TAG, "onIdleStart");
        Log.i(TAG, "onStartJob");
        final PackageManagerService pm =
                (PackageManagerService)ServiceManager.getService("package");

        if (pm.isStorageLow()) {
            schedule(BackgroundDexOptService.this, RETRY_LATENCY);
            Log.i(TAG, "Low storage, skipping this run");
            return false;
        }
        final ArraySet<String> pkgs = pm.getPackagesThatNeedDexOpt();
        if (pkgs == null) {
        final ArraySet<String> pkgs = pm.getOptimizablePackages();
        if (pkgs == null || pkgs.isEmpty()) {
            Log.i(TAG, "No packages to optimize");
            return false;
        }

@@ -83,15 +86,14 @@ public class BackgroundDexOptService extends JobService {
            public void run() {
                for (String pkg : pkgs) {
                    if (!mIdleTime.get()) {
                        // stopped while still working, so we need to reschedule
                        schedule(BackgroundDexOptService.this, 0);
                        // Out of the idle state. Stop the compilation.
                        return;
                    }
                    if (sFailedPackageNames.contains(pkg)) {
                        // skip previously failing package
                        continue;
                    }
                    if (!pm.performDexOpt(pkg, null /* instruction set */)) {
                    if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles)) {
                        // there was a problem running dexopt,
                        // remember this so we do not keep retrying.
                        sFailedPackageNames.add(pkg);
Loading