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

Commit ebd2ea0d authored by Arthur Eubanks's avatar Arthur Eubanks
Browse files

Start target package by binding to Service, not starting Activity

This reduces the stddev for a bunch of perf tests by quite a bit
(mostly the ones that rely on starting the package).

This is because previously the target
package was made to start running by starting an Activity, which takes
up CPU cycles.

Now we start a Service and wait for it to report back that its Looper
queue is idle, then proceed.

This does seem to slightly increase the runtime for some of the tests
though...

Some test numbers (only tests that have a large difference before and
after):

Before:
registeredBroadcast_mean=1920309
registeredBroadcast_median=1724844
registeredBroadcast_stddev=559809
manifestBroadcastRunning_mean=2395693
manifestBroadcastRunning_median=2063385
manifestBroadcastRunning_stddev=809836
contentProviderRunning_mean=668463
contentProviderRunning_median=588125
contentProviderRunning_stddev=214116
bindServiceAllowOomManagement_mean=1952431
bindServiceAllowOomManagement_median=2017682
bindServiceAllowOomManagement_stddev=289311
bindServiceAlreadyBound_mean=2146257
bindServiceAlreadyBound_median=2022891
bindServiceAlreadyBound_stddev=614549
bindServiceRunning_mean=4947541
bindServiceRunning_median=4710521
bindServiceRunning_stddev=962094
startServiceProcessRunningReadUriPermission_mean=1914106
startServiceProcessRunningReadUriPermission_median=1915209
startServiceProcessRunningReadUriPermission_stddev=196136
startServiceProcessRunning_mean=2841122
startServiceProcessRunning_median=2564792
startServiceProcessRunning_stddev=684654

After:
registeredBroadcast_mean=2559587
registeredBroadcast_median=2579792
registeredBroadcast_stddev=191377
manifestBroadcastRunning_mean=2709707
manifestBroadcastRunning_median=2725365
manifestBroadcastRunning_stddev=165661
contentProviderRunning_mean=663058
contentProviderRunning_median=639062
contentProviderRunning_stddev=97864
bindServiceAllowOomManagement_mean=1899179
bindServiceAllowOomManagement_median=1932553
bindServiceAllowOomManagement_stddev=184329
bindServiceAlreadyBound_mean=2023920
bindServiceAlreadyBound_median=2051614
bindServiceAlreadyBound_stddev=159993
bindServiceRunning_mean=6683975
bindServiceRunning_median=6753699
bindServiceRunning_stddev=475811
startServiceProcessRunningReadUriPermission_mean=2388997
startServiceProcessRunningReadUriPermission_median=2405365
startServiceProcessRunningReadUriPermission_stddev=244184
startServiceProcessRunning_mean=3384101
startServiceProcessRunning_median=3388282
startServiceProcessRunning_stddev=207333

Test: m ActivityManagerPerfTestsTestApp ActivityManagerPerfTests
Test: adb install \
$OUT/data/app/ActivityManagerPerfTestsTestApp/ActivityManagerPerfTestsTestApp.apk
Test: adb install \
$OUT/data/app/ActivityManagerPerfTests/ActivityManagerPerfTests.apk
Test: adb shell am instrument -w \
com.android.frameworks.perftests.amtests/android.support.test.runner.AndroidJUnitRunner

BUG: 67460485
Change-Id: Iaaaf7d8db885cc1149e74cb7ce4b47a295ab20e4
parent 6ccc053d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
            android:minSdkVersion="21"
            android:targetSdkVersion="27" />
    <application android:name=".TestApplication">
        <activity android:name=".TestActivity" android:exported="true"/>
        <provider
                android:authorities="com.android.frameworks.perftests.amteststestapp"
                android:name=".TestContentProvider"
@@ -32,6 +31,9 @@
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <service
                android:name=".StartProcessService"
                android:exported="true" />
        <service
                android:name=".TestService"
                android:exported="true" />
+14 −7
Original line number Diff line number Diff line
@@ -16,19 +16,26 @@

package com.android.frameworks.perftests.amteststestapp;

import android.app.Activity;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;

import com.android.frameworks.perftests.am.util.Constants;
import com.android.frameworks.perftests.am.util.Utils;

public class TestActivity extends Activity {
/**
 * Service used to start up the target package and make sure it's running.
 * Should be bound to, then wait for it to call the ILooperIdleCallback.
 */
public class StartProcessService extends Service {
    @Override
    protected void onResume() {
        super.onResume();
        Looper.myQueue().addIdleHandler(() -> {
            Utils.sendTime(getIntent(), Constants.TYPE_TARGET_PACKAGE_START);
    public IBinder onBind(Intent intent) {
        Looper.getMainLooper().getQueue().addIdleHandler(() -> {
            Utils.sendLooperIdle(intent);
            return false;
        });
        return new Binder();
    }
}
+7 −54
Original line number Diff line number Diff line
@@ -16,11 +16,9 @@

package com.android.frameworks.perftests.am.tests;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.PerfManualStatusReporter;
import android.support.test.InstrumentationRegistry;
@@ -28,20 +26,16 @@ import android.support.test.InstrumentationRegistry;
import com.android.frameworks.perftests.am.util.TargetPackageUtils;
import com.android.frameworks.perftests.am.util.TimeReceiver;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.LongSupplier;

public class BasePerfTest {
    private static final String TAG = BasePerfTest.class.getSimpleName();
    private static final long AWAIT_SERVICE_CONNECT_MS = 2000;

    private TimeReceiver mTimeReceiver;
    private ServiceConnection mAliveServiceConnection;

    @Rule
    public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
@@ -54,11 +48,6 @@ public class BasePerfTest {
        mTimeReceiver = new TimeReceiver();
    }

    @After
    public void tearDown() {
        TargetPackageUtils.killTargetPackage(mContext);
    }

    protected void addReceivedTimeNs(String type) {
        mTimeReceiver.addTimeForTypeToQueue(type, System.nanoTime());
    }
@@ -71,46 +60,6 @@ public class BasePerfTest {
        return intent;
    }

    protected ServiceConnection bindAndWaitForConnectedService() {
        return bindAndWaitForConnectedService(0);
    }

    protected ServiceConnection bindAndWaitForConnectedService(int flags) {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        final ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                countDownLatch.countDown();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };

        final Intent intent = createServiceIntent();
        final boolean success = mContext.bindService(intent, serviceConnection,
                Context.BIND_AUTO_CREATE | flags);
        Assert.assertTrue("Could not bind to service", success);

        try {
            boolean connectedSuccess = countDownLatch.await(AWAIT_SERVICE_CONNECT_MS,
                    TimeUnit.MILLISECONDS);
            Assert.assertTrue("Timeout when waiting for ServiceConnection.onServiceConnected()",
                    connectedSuccess);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return serviceConnection;
    }

    protected void unbindFromService(ServiceConnection serviceConnection) {
        if (serviceConnection != null) {
            mContext.unbindService(serviceConnection);
        }
    }

    protected Intent createBroadcastIntent(String action) {
        final Intent intent = new Intent(action);
        intent.addFlags(
@@ -125,11 +74,14 @@ public class BasePerfTest {

    private void setUpIteration() {
        mTimeReceiver.clear();
        TargetPackageUtils.killTargetPackage(mContext);
    }

    private void tearDownIteration() {
        TargetPackageUtils.killTargetPackage(mContext, mAliveServiceConnection);
    }

    protected void startTargetPackage() {
        TargetPackageUtils.startTargetPackage(mContext, mTimeReceiver);
        mAliveServiceConnection = TargetPackageUtils.startTargetPackage(mContext);
    }

    protected long getReceivedTimeNs(String type) {
@@ -142,6 +94,7 @@ public class BasePerfTest {
        while (benchmarkState.keepRunning(elapsedTimeNs)) {
            setUpIteration();
            elapsedTimeNs = func.getAsLong();
            tearDownIteration();
        }
    }
}
+12 −9
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;

import com.android.frameworks.perftests.am.util.Constants;
import com.android.frameworks.perftests.am.util.TargetPackageUtils;

import org.junit.Assert;
import org.junit.Test;
@@ -75,7 +76,7 @@ public class ServiceBindPerfTest extends BasePerfTest {
                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
                return endTimeNs - startTimeNs;
            } finally {
                unbindFromService(serviceConnection);
                TargetPackageUtils.unbindFromService(mContext, serviceConnection);
            }
        });
    }
@@ -97,7 +98,7 @@ public class ServiceBindPerfTest extends BasePerfTest {
                final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
                return endTimeNs - startTimeNs;
            } finally {
                unbindFromService(serviceConnection);
                TargetPackageUtils.unbindFromService(mContext, serviceConnection);
            }
        });
    }
@@ -112,7 +113,8 @@ public class ServiceBindPerfTest extends BasePerfTest {
            startTargetPackage();

            final Intent intent = createServiceIntent();
            final ServiceConnection alreadyBoundServiceConnection = bindAndWaitForConnectedService();
            final ServiceConnection alreadyBoundServiceConnection =
                    TargetPackageUtils.bindAndWaitForConnectedService(mContext, intent);

            try {
                final ServiceConnection serviceConnection = createServiceConnectionReportTime();
@@ -123,10 +125,10 @@ public class ServiceBindPerfTest extends BasePerfTest {
                    final long endTimeNs = getReceivedTimeNs(Constants.TYPE_SERVICE_CONNECTED);
                    return endTimeNs - startTimeNs;
                } finally {
                    unbindFromService(serviceConnection);
                    TargetPackageUtils.unbindFromService(mContext, serviceConnection);
                }
            } finally {
                unbindFromService(alreadyBoundServiceConnection);
                TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection);
            }
        });
    }
@@ -139,7 +141,8 @@ public class ServiceBindPerfTest extends BasePerfTest {
    public void bindServiceAllowOomManagement() {
        runPerfFunction(() -> {
            final Intent intentNoOom = createServiceIntent();
            final ServiceConnection serviceConnectionOom = bindAndWaitForConnectedService(
            final ServiceConnection serviceConnectionOom =
                    TargetPackageUtils.bindAndWaitForConnectedService(mContext, intentNoOom,
                            Context.BIND_ALLOW_OOM_MANAGEMENT);

            try {
@@ -152,10 +155,10 @@ public class ServiceBindPerfTest extends BasePerfTest {

                    return endTimeNs - startTimeNs;
                } finally {
                    unbindFromService(serviceConnectionNoOom);
                    TargetPackageUtils.unbindFromService(mContext, serviceConnectionNoOom);
                }
            } finally {
                unbindFromService(serviceConnectionOom);
                TargetPackageUtils.unbindFromService(mContext, serviceConnectionOom);
            }
        });
    }
+8 −5
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;

import com.android.frameworks.perftests.am.util.Constants;
import com.android.frameworks.perftests.am.util.TargetPackageUtils;

import org.junit.Assert;
import org.junit.Test;
@@ -86,7 +87,8 @@ public class ServiceStartPerfTest extends BasePerfTest {
    public void startServiceAlreadyBound() {
        runPerfFunction(() -> {
            final ServiceConnection alreadyBoundServiceConnection =
                    bindAndWaitForConnectedService();
                    TargetPackageUtils.bindAndWaitForConnectedService(mContext,
                            createServiceIntent());
            try {
                final Intent intent = createServiceIntent();

@@ -96,20 +98,21 @@ public class ServiceStartPerfTest extends BasePerfTest {

                return endTimeNs - startTimeNs;
            } finally {
                unbindFromService(alreadyBoundServiceConnection);
                TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection);
            }
        });
    }

    /**
     * Benchmark time from Context.startService() with FLAG_GRANT_READ_URI_PERMISSION to
     * Service.onStartCommand() when target process is running.
     * Service.onStartCommand() when target service is already running.
     */
    @Test
    public void startServiceProcessRunningReadUriPermission() {
        runPerfFunction(() -> {
            final ServiceConnection alreadyBoundServiceConnection =
                    bindAndWaitForConnectedService();
                    TargetPackageUtils.bindAndWaitForConnectedService(mContext,
                            createServiceIntent());
            try {
                final Intent intent = createServiceIntent();
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -120,7 +123,7 @@ public class ServiceStartPerfTest extends BasePerfTest {

                return endTimeNs - startTimeNs;
            } finally {
                unbindFromService(alreadyBoundServiceConnection);
                TargetPackageUtils.unbindFromService(mContext, alreadyBoundServiceConnection);
            }
        });
    }
Loading