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

Commit dd87ba45 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Denoise hermetric surfaceflinger perf tests

Remove overheard by disabling features during the test including:
- perfetto tracing
- region sampling by hiding navbar
- transaction tracing

Reduce variations between each frame by
- forcing max frame rate (avoids any frame misses)
- consuming transform hint (avoids gpu comp)
- starting simpleperf after test setup to move test activity
launch outside of measurement window

Test: atest android.surfaceflinger.SurfaceFlingerPerfTest
Bug: 298240242
Change-Id: Ida7422c37b9afa323147949c9776c042ca97cd08
parent 6a853abc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ android_test {
        "apct-perftests-utils",
        "collector-device-lib",
        "platform-test-annotations",
        "cts-wm-util",
    ],
    test_suites: ["device-tests"],
    data: [":perfetto_artifacts"],
+3 −1
Original line number Diff line number Diff line
@@ -16,9 +16,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="android.perftests.surfaceflinger">

    <!-- permission needed to write perfetto trace and read/write simpleperf report -->
    <!-- permission needed to read/write simpleperf report -->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- permission needed to disable tracing -->
    <uses-permission android:name="android.permission.HARDWARE_TEST" />

    <application android:label="SurfaceFlingerPerfTests">
        <uses-library android:name="android.test.runner" />
+2 −9
Original line number Diff line number Diff line
@@ -44,17 +44,12 @@
        <option name="hidden-api-checks" value="false"/>

        <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
        <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener,android.device.collectors.SimpleperfListener" />

        <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
        <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
        <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.SimpleperfListener" />

        <option name="instrumentation-arg" key="profiling-iterations" value="525" />
        <!-- PerfettoListener related arguments -->
        <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
        <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />

        <!-- SimpleperfListener related arguments -->
        <option name="instrumentation-arg" key="record" value="false"/>
        <option name="instrumentation-arg" key="report" value="true" />
        <option name="instrumentation-arg" key="arguments" value="-g" />
        <option name="instrumentation-arg" key="events_to_record" value="instructions,cpu-cycles,raw-l3d-cache-refill,sched:sched_waking" />
@@ -70,13 +65,11 @@
        <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
        <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
        <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />

    </test>

    <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
        <option name="directory-keys" value="/data/local/tmp/SurfaceFlingerPerfTests" />
        <!-- Needed for pulling the collected trace config on to the host -->
        <option name="pull-pattern-keys" value="perfetto_file_path" />
        <option name="pull-pattern-keys" value="simpleperf_file_path" />
    </metrics_collector>

+17 −5
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.surfaceflinger;

import static android.view.SurfaceControl.BUFFER_TRANSFORM_IDENTITY;
import static android.view.SurfaceControl.BUFFER_TRANSFORM_ROTATE_270;
import static android.view.SurfaceControl.BUFFER_TRANSFORM_ROTATE_90;

import android.annotation.ColorInt;
import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
@@ -33,9 +37,11 @@ import java.util.concurrent.ArrayBlockingQueue;
 * @hide
 */
public class BufferFlinger {
    private final int mTransformHint;
    ArrayBlockingQueue<GraphicBuffer> mBufferQ;

    public BufferFlinger(int numOfBuffers, @ColorInt int color) {
    public BufferFlinger(int numOfBuffers, @ColorInt int color, int bufferTransformHint) {
        mTransformHint = bufferTransformHint;
        mBufferQ = new ArrayBlockingQueue<>(numOfBuffers);

        while (numOfBuffers > 0) {
@@ -56,12 +62,18 @@ public class BufferFlinger {
    public void addBuffer(SurfaceControl.Transaction t, SurfaceControl surfaceControl) {
        try {
            final GraphicBuffer buffer = mBufferQ.take();
            t.setBuffer(surfaceControl,
            int transform = BUFFER_TRANSFORM_IDENTITY;
            if (mTransformHint == BUFFER_TRANSFORM_ROTATE_90) {
                transform = BUFFER_TRANSFORM_ROTATE_270;
            } else if (mTransformHint == BUFFER_TRANSFORM_ROTATE_270) {
                transform = BUFFER_TRANSFORM_ROTATE_90;
            }
            t.setBufferTransform(surfaceControl, transform);
            t.setBuffer(
                    surfaceControl,
                    HardwareBuffer.createFromGraphicBuffer(buffer),
                    null,
                    (SyncFence fence) -> {
                        releaseCallback(fence, buffer);
                    });
                    (SyncFence fence) -> releaseCallback(fence, buffer));
        } catch (InterruptedException ignore) {
        }
    }
+62 −6
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.surfaceflinger;

import static android.server.wm.CtsWindowInfoUtils.waitForWindowOnTop;

import android.app.Instrumentation;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -25,12 +28,13 @@ import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.helpers.SimpleperfHelper;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -39,6 +43,8 @@ import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Random;

@@ -63,12 +69,33 @@ public class SurfaceFlingerPerfTest {
    public final RuleChain mAllRules = RuleChain
            .outerRule(mActivityRule);

    private int mTransformHint;
    private SimpleperfHelper mSimpleperfHelper = new SimpleperfHelper();

    /** Start simpleperf sampling. */
    public void startSimpleperf(String subcommand, String arguments) {
        if (!mSimpleperfHelper.startCollecting(subcommand, arguments)) {
            Log.e(TAG, "Simpleperf did not start successfully.");
        }
    }

    /** Stop simpleperf sampling and dump the collected file into the given path. */
    private void stopSimpleperf(Path path) {
        if (!mSimpleperfHelper.stopCollecting(path.toString())) {
            Log.e(TAG, "Failed to collect the simpleperf output.");
        }
    }

    @BeforeClass
    public static void suiteSetup() {
        final Bundle arguments = InstrumentationRegistry.getArguments();
        sProfilingIterations = Integer.parseInt(
                arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
        Log.d(TAG, "suiteSetup: mProfilingIterations = " + sProfilingIterations);
        // disable transaction tracing
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .executeShellCommand("service call SurfaceFlinger 1041 i32 -1");
    }

    @Before
@@ -77,17 +104,45 @@ public class SurfaceFlingerPerfTest {
        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        for (int i = 0; i < MAX_BUFFERS; i++) {
            SurfaceControl sc = createSurfaceControl();
            BufferFlinger bufferTracker = createBufferTracker(Color.argb(getRandomColorComponent(),
                    getRandomColorComponent(), getRandomColorComponent(),
                    getRandomColorComponent()));
            BufferFlinger bufferTracker =
                    createBufferTracker(
                            Color.argb(
                                    getRandomColorComponent(),
                                    getRandomColorComponent(),
                                    getRandomColorComponent(),
                                    getRandomColorComponent()),
                            mActivity.getBufferTransformHint());
            bufferTracker.addBuffer(t, sc);
            t.setPosition(sc, i * 10, i * 10);
        }
        t.apply(true);
        mBufferTrackers.get(0).addBuffer(mTransaction, mSurfaceControls.get(0));
        mTransaction.show(mSurfaceControls.get(0)).apply(true);
        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();

        instrumentation.waitForIdleSync();
        // Wait for device animation that shows above the activity to leave.
        try {
            waitForWindowOnTop(mActivity.getWindow());
        } catch (InterruptedException e) {
            Log.e(TAG, "Failed to wait for window", e);
        }
        String args =
                "-o /data/local/tmp/perf.data -g -e"
                    + " instructions,cpu-cycles,raw-l3d-cache-refill,sched:sched_waking -p "
                        + mSimpleperfHelper.getPID("surfaceflinger")
                        + ","
                        + mSimpleperfHelper.getPID("android.perftests.surfaceflinger");
        startSimpleperf("record", args);
    }

    @After
    public void teardown() {
        try {
            mSimpleperfHelper.stopSimpleperf();
        } catch (IOException e) {
            Log.e(TAG, "Failed to stop simpleperf", e);
        }
        mSurfaceControls.forEach(SurfaceControl::release);
        mBufferTrackers.forEach(BufferFlinger::freeBuffers);
    }
@@ -97,8 +152,9 @@ public class SurfaceFlingerPerfTest {
    }

    private final ArrayList<BufferFlinger> mBufferTrackers = new ArrayList<>();
    private BufferFlinger createBufferTracker(int color) {
        BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);

    private BufferFlinger createBufferTracker(int color, int bufferTransformHint) {
        BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color, bufferTransformHint);
        mBufferTrackers.add(bufferTracker);
        return bufferTracker;
    }
Loading