Setup crystalball and add more perf tests

crystalball is the new perf system that we are migrating to.

The perf tests on platform side are repurposed to benchmark the platform
code and various overheads introduced by the system.
The model performance will be tracked elsewhere.

Bug: 161918490
Bug: 156886144

Test: atest TextClassifierPerfsTest
Change-Id: Ib9d204a930f5212a68407dbab576627a51dfb41e
This commit is contained in:
Tony Mak
2020-08-03 12:23:51 +01:00
parent ed575dce24
commit 833b293509
3 changed files with 85 additions and 51 deletions

View File

@@ -19,7 +19,9 @@ android_test {
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
"collector-device-lib-platform",
],
data: [":perfetto_artifacts"],
platform_apis: true,
test_suites: ["device-tests"],
}

View File

@@ -21,8 +21,40 @@
<option name="test-file-name" value="TextClassifierPerfTests.apk" />
</target_preparer>
<!-- Needed for pushing the trace config file -->
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
</target_preparer>
<!-- Needed for pulling the collected trace config on to the host -->
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="pull-pattern-keys" value="perfetto_file_path" />
</metrics_collector>
<!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
<option name="isolated-storage" value="false" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.perftests.textclassifier" />
<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" />
<!-- 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" />
<!-- ProcLoadListener related arguments -->
<!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
<option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
<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" />
<!-- 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" />
<option name="instrumentation-arg" key="newRunListenerMode" value="true" />
</test>
</configuration>

View File

@@ -18,6 +18,7 @@ package android.view.textclassifier;
import android.content.Context;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.service.textclassifier.TextClassifierService;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
@@ -25,48 +26,73 @@ import androidx.test.filters.LargeTest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Random;
@RunWith(Parameterized.class)
@LargeTest
public class TextClassifierPerfTest {
/** Request contains meaning text, rather than garbled text. */
private static final int ACTUAL_REQUEST = 0;
private static final String RANDOM_CHAR_SET = "abcdefghijklmnopqrstuvwxyz0123456789";
private static final String TEXT = " Oh hi Mark, the number is (323) 654-6192.\n"
+ "Anyway, I'll meet you at 1600 Pennsylvania Avenue NW.\n"
+ "My flight is LX 38 and I'll arrive at 8:00pm.\n"
+ "Also, check out www.google.com.\n";
@Rule
public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@Parameterized.Parameters(name = "size{0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{{ACTUAL_REQUEST}, {10}, {100}, {1000}});
}
private TextClassifier mTextClassifier;
private final int mSize;
public TextClassifierPerfTest(int size) {
mSize = size;
}
@Before
public void setUp() {
Context context = InstrumentationRegistry.getTargetContext();
TextClassificationManager textClassificationManager =
context.getSystemService(TextClassificationManager.class);
mTextClassifier = textClassificationManager.getTextClassifier(TextClassifier.LOCAL);
mTextClassifier = TextClassifierService.getDefaultTextClassifierImplementation(context);
}
@Test
public void testClassifyText() {
TextClassification.Request request =
new TextClassification.Request.Builder(TEXT, 0, TEXT.length()).build();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mTextClassifier.classifyText(request);
}
}
@Test
public void testSuggestSelection() {
// Trying to select the phone number.
TextSelection.Request request =
new TextSelection.Request.Builder(
TEXT,
/* startIndex= */ 28,
/* endIndex= */29)
.build();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mTextClassifier.suggestSelection(request);
}
}
@Test
public void testGenerateLinks() {
TextLinks.Request request =
new TextLinks.Request.Builder(TEXT).build();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mTextClassifier.generateLinks(request);
}
}
@Test
public void testSuggestConversationActions() {
String text = mSize == ACTUAL_REQUEST ? "Where are you?" : generateRandomString(mSize);
ConversationActions.Request request = createConversationActionsRequest(text);
ConversationActions.Message message =
new ConversationActions.Message.Builder(
ConversationActions.Message.PERSON_USER_OTHERS)
.setText(TEXT)
.build();
ConversationActions.Request request = new ConversationActions.Request.Builder(
Collections.singletonList(message))
.build();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mTextClassifier.suggestConversationActions(request);
@@ -75,36 +101,10 @@ public class TextClassifierPerfTest {
@Test
public void testDetectLanguage() {
String text = mSize == ACTUAL_REQUEST
? "これは日本語のテキストです" : generateRandomString(mSize);
TextLanguage.Request request = createTextLanguageRequest(text);
TextLanguage.Request request = new TextLanguage.Request.Builder(TEXT).build();
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
mTextClassifier.detectLanguage(request);
}
}
private static ConversationActions.Request createConversationActionsRequest(CharSequence text) {
ConversationActions.Message message =
new ConversationActions.Message.Builder(
ConversationActions.Message.PERSON_USER_OTHERS)
.setText(text)
.build();
return new ConversationActions.Request.Builder(Collections.singletonList(message))
.build();
}
private static TextLanguage.Request createTextLanguageRequest(CharSequence text) {
return new TextLanguage.Request.Builder(text).build();
}
private static String generateRandomString(int length) {
Random random = new Random();
StringBuilder stringBuilder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int index = random.nextInt(RANDOM_CHAR_SET.length());
stringBuilder.append(RANDOM_CHAR_SET.charAt(index));
}
return stringBuilder.toString();
}
}