summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author felkachang <felkachang@google.com> 2022-09-01 16:56:52 +0800
committer felkachang <felkachang@google.com> 2022-09-22 12:42:26 +0800
commita07f4f5532d8386c1824ec0029f422dae3cf4015 (patch)
tree684bc66d0eabc52b47b994522035572dedacc81d
parentfc2de301f00c240f07ed541ef2f49687de26a4f6 (diff)
Add the benchmark of XmlBlock for CriticalNative
In order to make sure that CriticalNative is better than "FastNaive", this patch adds android.content.res.XmlBlockBenchmark to measure the current performance of FastNaive. Bug: 173709508 Test: atest \ CorePerfTests:android.content.res.XmlBlockBenchmark Change-Id: Iafa1e043425353bf430832ee5edd38947e667404
-rw-r--r--apct-tests/perftests/core/AndroidTest.xml5
-rw-r--r--apct-tests/perftests/core/res/layout/linear_layout_for_xmlblock_benchmark.xml110
-rw-r--r--apct-tests/perftests/core/src/android/content/res/XmlBlockBenchmark.java321
3 files changed, 436 insertions, 0 deletions
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml
index 4f8ee2927d51..86f41e1f496c 100644
--- a/apct-tests/perftests/core/AndroidTest.xml
+++ b/apct-tests/perftests/core/AndroidTest.xml
@@ -27,6 +27,11 @@
<option name="test-file-name" value="CorePerfTests.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
+ </target_preparer>
+
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="pull-pattern-keys" value="perfetto_file_path" />
</metrics_collector>
diff --git a/apct-tests/perftests/core/res/layout/linear_layout_for_xmlblock_benchmark.xml b/apct-tests/perftests/core/res/layout/linear_layout_for_xmlblock_benchmark.xml
new file mode 100644
index 000000000000..9005d6fa9e76
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/linear_layout_for_xmlblock_benchmark.xml
@@ -0,0 +1,110 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/linear_layout_root"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="10dp" >
+
+ <view class="com.android.systemui.statusbar.policy.RemoteInputView$RemoteEditText"
+ android:id="@+id/remote_input_text"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_weight="1"
+ android:paddingTop="14dp"
+ android:paddingStart="4dp"
+ android:paddingBottom="16dp"
+ android:paddingEnd="12dp"
+ android:layout_gravity="start|center_vertical"
+ android:textAppearance="?android:attr/textAppearance"
+ android:textSize="16sp"
+ android:background="@null"
+ android:maxLines="4"
+ android:ellipsize="start"
+ android:inputType="textShortMessage|textMultiLine|textAutoCorrect|textCapSentences"
+ android:imeOptions="actionSend|flagNoExtractUi|flagNoFullscreen" />
+
+ <ImageButton
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ style="@android:style/MediaButton.Previous"
+ id="@+id/my_image_button_previous"
+ />
+
+ <ImageButton
+ id="@+id/my_image_button_next"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ style="@android:style/MediaButton.Next"
+ />
+
+ <LinearLayout
+ id="@+id/my_linear_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="10dp" >
+
+ <ImageButton
+ android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true" />
+
+ <LinearLayout
+ id="@+id/my_inner_linear_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="10dp" >
+
+ <ImageButton
+ android:id="@+id/button5"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true" />
+ </LinearLayout>
+
+ <ImageButton
+ android:id="@+id/button4"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button2"
+ android:layout_centerHorizontal="true" />
+
+ <ImageButton
+ android:id="@+id/button6"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_above="@+id/button4"
+ android:layout_centerHorizontal="true" />
+
+ <ImageButton
+ android:id="@+id/button7"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/button"
+ android:layout_toEndOf="@+id/button"
+ android:layout_toRightOf="@+id/button" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/apct-tests/perftests/core/src/android/content/res/XmlBlockBenchmark.java b/apct-tests/perftests/core/src/android/content/res/XmlBlockBenchmark.java
new file mode 100644
index 000000000000..bdce902e4aef
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/content/res/XmlBlockBenchmark.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.START_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.START_TAG;
+
+import android.content.Context;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.perftests.core.R;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+@LargeTest
+public class XmlBlockBenchmark {
+ private static final String TAG = "XmlBlockBenchmark";
+ private static final String NAMESPACE_ANDROID = "http://schemas.android.com/apk/res/android";
+
+ @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ private XmlBlock.Parser mParser;
+
+ private void cleanCache() {
+ if (mParser != null) {
+ mParser.close();
+ }
+
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final Resources resources = context.getResources();
+ resources.getImpl().clearAllCaches();
+ Log.d(TAG, "cleanCache");
+ }
+
+ private XmlBlock.Parser getNewParser() {
+ cleanCache();
+
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ final Resources resources = context.getResources();
+ return (XmlBlock.Parser) resources.getXml(R.layout.linear_layout_for_xmlblock_benchmark);
+ }
+
+ @Before
+ public void setUp() {
+ mParser = getNewParser();
+ }
+
+ @After
+ public void tearDown() {
+ cleanCache();
+ }
+
+ int safeNext() throws XmlPullParserException, IOException {
+ while (true) {
+ int parseState = mParser.next();
+ if (parseState == START_TAG) {
+ return parseState;
+ } else if (parseState == END_DOCUMENT) {
+ mParser = getNewParser();
+ }
+ }
+ }
+
+ @Test
+ public void throwNpeCausedByNullDocument() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ mParser.close();
+ while (state.keepRunning()) {
+ try {
+ mParser.getClassAttribute();
+ } catch (NullPointerException e) {
+ continue;
+ }
+ Assert.fail("It shouldn't be here!");
+ }
+ }
+
+ @Test
+ public void getNext() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ int parseState = mParser.next();
+ state.pauseTiming();
+ if (parseState == END_DOCUMENT) {
+ mParser = getNewParser();
+ }
+ state.resumeTiming();
+ }
+ }
+
+ private <T> void benchmarkTagFunction(BenchmarkState state, String name,
+ Supplier<T> measureTarget)
+ throws XmlPullParserException, IOException {
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ int parseState = safeNext();
+
+ if (parseState != END_DOCUMENT) {
+ final String tagName = mParser.getName();
+ state.resumeTiming();
+ final T value = measureTarget.get();
+ state.pauseTiming();
+ Log.d(TAG,
+ TextUtils.formatSimple("%s() in tag %s is %s", name, tagName, value));
+ }
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void getNamespace() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getNamespace", () -> mParser.getNamespace());
+ }
+
+ @Test
+ public void getName() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getName", () -> mParser.getName());
+ }
+
+ @Test
+ public void getText() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getText", () -> mParser.getText());
+ }
+
+ @Test
+ public void getLineNumber() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getLineNumber", () -> mParser.getLineNumber());
+ }
+
+ @Test
+ public void getAttributeCount() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getAttributeCount", () -> mParser.getAttributeCount());
+ }
+
+ private <T> void benchmarkAttributeFunction(BenchmarkState state, String name,
+ Function<Integer, T> measureTarget)
+ throws XmlPullParserException, IOException {
+ boolean needNext = true;
+ boolean needGetCount = false;
+ int attributeCount = 0;
+ int i = 0;
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ if (needNext) {
+ int parseState = safeNext();
+ if (parseState == START_TAG) {
+ needNext = false;
+ needGetCount = true;
+ }
+ }
+
+ if (needGetCount) {
+ attributeCount = mParser.getAttributeCount();
+ needGetCount = false;
+ i = 0;
+ }
+
+ if (i < attributeCount) {
+ final String tagName = mParser.getName();
+ final String attributeName = mParser.getAttributeName(i);
+ state.resumeTiming();
+ final T value = measureTarget.apply(i);
+ state.pauseTiming();
+ Log.d(TAG,
+ TextUtils.formatSimple("%s(%d:%s) in tag %s is %s", name, i, attributeName,
+ tagName, value));
+ i++;
+ }
+
+ if (i >= attributeCount) {
+ needNext = true;
+ }
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void getAttributeNamespace() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkAttributeFunction(state, "getAttributeNamespace",
+ attributeIndex -> mParser.getAttributeNamespace(attributeIndex));
+ }
+
+ @Test
+ public void getAttributeName() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkAttributeFunction(state, "getAttributeName",
+ attributeIndex -> mParser.getAttributeName(attributeIndex));
+ }
+
+ @Test
+ public void getAttributeNameResource() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkAttributeFunction(state, "getAttributeNameResource",
+ attributeIndex -> mParser.getAttributeNameResource(attributeIndex));
+ }
+
+ /**
+ * benchmark {@link android.content.res.XmlBlock#nativeGetAttributeDataType(long, int)} and
+ * {@link android.content.res.XmlBlock#nativeGetAttributeData(long, int)}
+ */
+ @Test
+ public void getAttributeDataXXX() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkAttributeFunction(state, "getAttributeDataXXX",
+ attributeIndex -> mParser.getAttributeValue(attributeIndex));
+ }
+
+ @Test
+ public void getSourceResId() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getSourceResId", () -> mParser.getSourceResId());
+ }
+
+ @Test
+ public void getIdAttribute() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getIdAttribute", () -> mParser.getIdAttribute());
+ }
+
+ @Test
+ public void getClassAttribute() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getClassAttribute", () -> mParser.getClassAttribute());
+ }
+
+ @Test
+ public void getStyleAttribute() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getStyleAttribute", () -> mParser.getStyleAttribute());
+ }
+
+ @Test
+ public void getAttributeIndex() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ benchmarkTagFunction(state, "getAttributeValue",
+ () -> mParser.getAttributeValue(NAMESPACE_ANDROID, "layout_width"));
+ }
+
+ @Test
+ public void parseOneXmlDocument() throws XmlPullParserException, IOException {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ mParser = getNewParser();
+ state.resumeTiming();
+
+ int parseState;
+ while ((parseState = mParser.next()) != END_DOCUMENT) {
+ if (parseState == START_DOCUMENT) {
+ state.pauseTiming();
+ Log.d(TAG, "parseOneXmlDocument: start document");
+ state.resumeTiming();
+ } else if (parseState == START_TAG) {
+ final String tagName = mParser.getName();
+ state.pauseTiming();
+ Log.d(TAG, TextUtils.formatSimple("parseOneXmlDocument: tag %s {[", tagName));
+ state.resumeTiming();
+ for (int i = 0, count = mParser.getAttributeCount(); i < count; i++) {
+ final String attributeName = mParser.getAttributeName(i);
+ final String attributeValue = mParser.getAttributeValue(i);
+
+ state.pauseTiming();
+ Log.d(TAG, TextUtils.formatSimple(
+ "parseOneXmlDocument: attribute %d {%s = %s},", i, attributeName,
+ attributeValue));
+ state.resumeTiming();
+ }
+ state.pauseTiming();
+ Log.d(TAG, "parseOneXmlDocument: ]");
+ state.resumeTiming();
+ } else if (parseState == END_TAG) {
+ state.pauseTiming();
+ Log.d(TAG, "parseOneXmlDocument: }");
+ state.resumeTiming();
+ } else {
+ final String text = mParser.getText();
+ state.pauseTiming();
+ Log.d(TAG, TextUtils.formatSimple(
+ "parseOneXmlDocument: parseState = %d, text = %s", parseState, text));
+ state.resumeTiming();
+ }
+ }
+ }
+ }
+}