diff options
author | 2023-09-21 21:58:03 -0700 | |
---|---|---|
committer | 2023-09-22 08:34:33 -0700 | |
commit | dd87ba45c6e04bbabb1d3b8a68a7495a8cdd3c5c (patch) | |
tree | 63b49ededb7a032af48bf442062fe5b9b03257a5 | |
parent | 6a853abcf3bed9189341816d30439b1706fa6f17 (diff) |
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
6 files changed, 100 insertions, 21 deletions
diff --git a/apct-tests/perftests/surfaceflinger/Android.bp b/apct-tests/perftests/surfaceflinger/Android.bp index 0c28bcef469c..21d0d44fdd2f 100644 --- a/apct-tests/perftests/surfaceflinger/Android.bp +++ b/apct-tests/perftests/surfaceflinger/Android.bp @@ -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"], diff --git a/apct-tests/perftests/surfaceflinger/AndroidManifest.xml b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml index 26f25863f055..aa55b01cc787 100644 --- a/apct-tests/perftests/surfaceflinger/AndroidManifest.xml +++ b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml @@ -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" /> diff --git a/apct-tests/perftests/surfaceflinger/AndroidTest.xml b/apct-tests/perftests/surfaceflinger/AndroidTest.xml index 58cf58b89782..6dcd86e156d9 100644 --- a/apct-tests/perftests/surfaceflinger/AndroidTest.xml +++ b/apct-tests/perftests/surfaceflinger/AndroidTest.xml @@ -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> diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java index 8a447bb801f2..8d6dd127645f 100644 --- a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java +++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java @@ -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) { } } diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java index dca818ec9708..fd9d99181fbf 100644 --- a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java +++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java @@ -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; } diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java index bb956596c7eb..5f1f44d826e5 100644 --- a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java +++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java @@ -16,12 +16,15 @@ package android.surfaceflinger; +import static android.view.Surface.FRAME_RATE_COMPATIBILITY_DEFAULT; + import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.SurfaceControl; import android.view.SurfaceHolder; import android.view.SurfaceView; +import android.view.View; import android.view.Window; import android.view.WindowManager; @@ -42,6 +45,11 @@ public class SurfaceFlingerTestActivity extends Activity { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + View decorView = getWindow().getDecorView(); + // Hide both the navigation bar and the status bar. + int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; + decorView.setSystemUiVisibility(uiOptions); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); mTestSurfaceView = new TestSurfaceView(this); setContentView(mTestSurfaceView); @@ -51,6 +59,10 @@ public class SurfaceFlingerTestActivity extends Activity { return mTestSurfaceView.getChildSurfaceControlHelper(); } + public int getBufferTransformHint() { + return mTestSurfaceView.getRootSurfaceControl().getBufferTransformHint(); + } + public class TestSurfaceView extends SurfaceView { public TestSurfaceView(Context context) { super(context); @@ -79,6 +91,9 @@ public class SurfaceFlingerTestActivity extends Activity { // check to see if surface is valid if (holder.getSurface().isValid()) { mSurfaceControl = getSurfaceControl(); + new SurfaceControl.Transaction() + .setFrameRate(mSurfaceControl, 1000, FRAME_RATE_COMPATIBILITY_DEFAULT) + .apply(true); } return new SurfaceControl.Builder() .setName("ChildSurfaceControl") |