SurfaceFlingerPerfTests: Reduce variability in results

- use custom interation counter since simpleperf is run over entire test
- move all setup to @Before so its not recorded by simpleperf
- make test activity fullscreen to remove buffer updates from statusbar

Bug: 230039226
Test: atest SurfaceFlingerPerfTest

Change-Id: Id8c03b4dd32c012f091ab602fff780308420742f
Merged-In: Id8c03b4dd32c012f091ab602fff780308420742f
This commit is contained in:
Vishnu Nair
2022-09-09 16:26:16 -07:00
parent 4b73f2a5eb
commit 451eb138d8
4 changed files with 115 additions and 133 deletions

View File

@@ -49,16 +49,20 @@
<!-- 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="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="report" value="true" />
<option name="instrumentation-arg" key="arguments" value="&quot;&quot;" />
<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" />
<option name="instrumentation-arg" key="processes_to_record" value="surfaceflinger" />
<option name="instrumentation-arg" key="symbols_to_report" value="&quot;android::SurfaceFlinger::commit(;android::SurfaceFlinger::composite(&quot;" />
<option name="instrumentation-arg" key="symbols_to_report" value="&quot;commit;android::SurfaceFlinger::commit(;composite;android::SurfaceFlinger::composite(&quot;" />
<!-- should match profiling-iterations -->
<option name="instrumentation-arg" key="test_iterations" value="525" />
<!-- ProcLoadListener related arguments -->
<!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->

View File

@@ -53,15 +53,17 @@ public class BufferFlinger {
}
}
public void addBuffer(SurfaceControl.Transaction t, SurfaceControl surfaceControl)
throws InterruptedException {
GraphicBuffer buffer = mBufferQ.take();
t.setBuffer(surfaceControl,
HardwareBuffer.createFromGraphicBuffer(buffer),
null,
(SyncFence fence) -> {
releaseCallback(fence, buffer);
});
public void addBuffer(SurfaceControl.Transaction t, SurfaceControl surfaceControl) {
try {
final GraphicBuffer buffer = mBufferQ.take();
t.setBuffer(surfaceControl,
HardwareBuffer.createFromGraphicBuffer(buffer),
null,
(SyncFence fence) -> {
releaseCallback(fence, buffer);
});
} catch (InterruptedException ignore) {
}
}
public void releaseCallback(SyncFence fence, GraphicBuffer buffer) {

View File

@@ -18,8 +18,8 @@ package android.surfaceflinger;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceControl;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
@@ -29,6 +29,7 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
@@ -40,65 +41,35 @@ import java.util.Random;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class SurfaceFlingerPerfTest {
protected ActivityScenarioRule<SurfaceFlingerTestActivity> mActivityRule =
private static final String TAG = "SurfaceFlingerPerfTest";
private final ActivityScenarioRule<SurfaceFlingerTestActivity> mActivityRule =
new ActivityScenarioRule<>(SurfaceFlingerTestActivity.class);
protected PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
private SurfaceFlingerTestActivity mActivity;
static final int BUFFER_COUNT = 2;
private static final int BUFFER_COUNT = 2;
private static final int MAX_BUFFERS = 10;
private static final int MAX_POSITION = 10;
private static final float MAX_SCALE = 2.0f;
private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
private static final String DEFAULT_PROFILING_ITERATIONS = "100";
private static int sProfilingIterations;
private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@Rule
public final RuleChain mAllRules = RuleChain
.outerRule(mPerfStatusReporter)
.around(mActivityRule);
.outerRule(mActivityRule);
@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);
}
@Before
public void setup() {
mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
}
@After
public void teardown() {
mSurfaceControls.forEach(SurfaceControl::release);
mByfferTrackers.forEach(BufferFlinger::freeBuffers);
}
private ArrayList<BufferFlinger> mByfferTrackers = new ArrayList<>();
private BufferFlinger createBufferTracker(int color) {
BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);
mByfferTrackers.add(bufferTracker);
return bufferTracker;
}
private ArrayList<SurfaceControl> mSurfaceControls = new ArrayList<>();
private SurfaceControl createSurfaceControl() throws InterruptedException {
SurfaceControl sc = mActivity.createChildSurfaceControl();
mSurfaceControls.add(sc);
return sc;
}
@Test
public void singleBuffer() throws Exception {
SurfaceControl sc = createSurfaceControl();
BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
bufferTracker.addBuffer(t, sc);
t.show(sc);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
bufferTracker.addBuffer(t, sc);
t.apply();
}
}
static int getRandomColorComponent() {
return new Random().nextInt(155) + 100;
}
@Test
public void multipleBuffers() throws Exception {
final int MAX_BUFFERS = 10;
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
for (int i = 0; i < MAX_BUFFERS; i++) {
SurfaceControl sc = createSurfaceControl();
@@ -107,122 +78,120 @@ public class SurfaceFlingerPerfTest {
getRandomColorComponent()));
bufferTracker.addBuffer(t, sc);
t.setPosition(sc, i * 10, i * 10);
t.show(sc);
}
t.apply(true);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
}
@After
public void teardown() {
mSurfaceControls.forEach(SurfaceControl::release);
mBufferTrackers.forEach(BufferFlinger::freeBuffers);
}
static int getRandomColorComponent() {
return new Random().nextInt(155) + 100;
}
private final ArrayList<BufferFlinger> mBufferTrackers = new ArrayList<>();
private BufferFlinger createBufferTracker(int color) {
BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);
mBufferTrackers.add(bufferTracker);
return bufferTracker;
}
private final ArrayList<SurfaceControl> mSurfaceControls = new ArrayList<>();
private SurfaceControl createSurfaceControl() {
SurfaceControl sc = mActivity.createChildSurfaceControl();
mSurfaceControls.add(sc);
return sc;
}
@Test
public void singleBuffer() throws Exception {
for (int i = 0; i < sProfilingIterations; i++) {
mBufferTrackers.get(0).addBuffer(mTransaction, mSurfaceControls.get(0));
mTransaction.show(mSurfaceControls.get(0)).apply(true);
}
}
@Test
public void multipleBuffers() throws Exception {
for (int j = 0; j < sProfilingIterations; j++) {
for (int i = 0; i < MAX_BUFFERS; i++) {
mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
mBufferTrackers.get(i).addBuffer(mTransaction, mSurfaceControls.get(i));
mTransaction.show(mSurfaceControls.get(i));
}
t.apply();
mTransaction.apply(true);
}
}
@Test
public void multipleOpaqueBuffers() throws Exception {
final int MAX_BUFFERS = 10;
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
for (int i = 0; i < MAX_BUFFERS; i++) {
SurfaceControl sc = createSurfaceControl();
BufferFlinger bufferTracker = createBufferTracker(Color.rgb(getRandomColorComponent(),
getRandomColorComponent(), getRandomColorComponent()));
bufferTracker.addBuffer(t, sc);
t.setOpaque(sc, true);
t.setPosition(sc, i * 10, i * 10);
t.show(sc);
}
t.apply(true);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int j = 0; j < sProfilingIterations; j++) {
for (int i = 0; i < MAX_BUFFERS; i++) {
mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
mBufferTrackers.get(i).addBuffer(mTransaction, mSurfaceControls.get(i));
mTransaction.show(mSurfaceControls.get(i)).setOpaque(mSurfaceControls.get(i), true);
}
t.apply();
mTransaction.apply(true);
}
}
@Test
public void geometryChanges() throws Exception {
final int MAX_POSITION = 10;
final float MAX_SCALE = 2.0f;
SurfaceControl sc = createSurfaceControl();
BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
bufferTracker.addBuffer(t, sc);
t.show(sc).apply(true);
int step = 0;
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int i = 0; i < sProfilingIterations; i++) {
step = ++step % MAX_POSITION;
t.setPosition(sc, step, step);
mTransaction.setPosition(mSurfaceControls.get(0), step, step);
float scale = ((step * MAX_SCALE) / MAX_POSITION) + 0.5f;
t.setScale(sc, scale, scale);
t.apply();
mTransaction.setScale(mSurfaceControls.get(0), scale, scale);
mTransaction.show(mSurfaceControls.get(0)).apply(true);
}
}
@Test
public void geometryWithBufferChanges() throws Exception {
final int MAX_POSITION = 10;
SurfaceControl sc = createSurfaceControl();
BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
bufferTracker.addBuffer(t, sc);
t.show(sc).apply(true);
int step = 0;
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int i = 0; i < sProfilingIterations; i++) {
step = ++step % MAX_POSITION;
t.setPosition(sc, step, step);
float scale = ((step * 2.0f) / MAX_POSITION) + 0.5f;
t.setScale(sc, scale, scale);
bufferTracker.addBuffer(t, sc);
t.apply();
mTransaction.setPosition(mSurfaceControls.get(0), step, step);
float scale = ((step * MAX_SCALE) / MAX_POSITION) + 0.5f;
mTransaction.setScale(mSurfaceControls.get(0), scale, scale);
mBufferTrackers.get(0).addBuffer(mTransaction, mSurfaceControls.get(0));
mTransaction.show(mSurfaceControls.get(0)).apply(true);
}
}
@Test
public void addRemoveLayers() throws Exception {
SurfaceControl sc = createSurfaceControl();
BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int i = 0; i < sProfilingIterations; i++) {
SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
.setName("childLayer").setBLASTLayer().build();
bufferTracker.addBuffer(t, childSurfaceControl);
t.reparent(childSurfaceControl, sc);
t.apply();
t.remove(childSurfaceControl).apply();
mBufferTrackers.get(0).addBuffer(mTransaction, childSurfaceControl);
mTransaction.reparent(childSurfaceControl, mSurfaceControls.get(0));
mTransaction.show(childSurfaceControl).show(mSurfaceControls.get(0));
mTransaction.apply(true);
mTransaction.remove(childSurfaceControl).apply(true);
}
}
@Test
public void displayScreenshot() throws Exception {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int i = 0; i < sProfilingIterations; i++) {
Bitmap screenshot =
InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
screenshot.recycle();
mTransaction.apply(true);
}
}
@Test
public void layerScreenshot() throws Exception {
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
for (int i = 0; i < sProfilingIterations; i++) {
Bitmap screenshot =
InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot(
mActivity.getWindow());
screenshot.recycle();
mTransaction.apply(true);
}
}
}

View File

@@ -22,6 +22,7 @@ import android.os.Bundle;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import java.util.concurrent.CountDownLatch;
@@ -38,12 +39,15 @@ public class SurfaceFlingerTestActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTestSurfaceView = new TestSurfaceView(this);
setContentView(mTestSurfaceView);
}
public SurfaceControl createChildSurfaceControl() throws InterruptedException {
public SurfaceControl createChildSurfaceControl() {
return mTestSurfaceView.getChildSurfaceControlHelper();
}
@@ -65,8 +69,11 @@ public class SurfaceFlingerTestActivity extends Activity {
});
}
public SurfaceControl getChildSurfaceControlHelper() throws InterruptedException {
mIsReady.await();
public SurfaceControl getChildSurfaceControlHelper() {
try {
mIsReady.await();
} catch (InterruptedException ignore) {
}
SurfaceHolder holder = getHolder();
// check to see if surface is valid