diff options
author | Tenghui Zhu <ztenghui@google.com> | 2016-07-12 20:41:57 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-07-12 20:41:59 +0000 |
commit | 19c6ae310c4d5cf86fd38126db7c342c6f56976b (patch) | |
tree | 0d952976200ff308de60e20aba7902962233c518 | |
parent | 3b457c74d98f8498e6cee85666d26482c220fb6c (diff) | |
parent | a9cebd628c53b900d48600a5e7ced546c91522e6 (diff) |
Merge "Add layout perf test into APCT"
7 files changed, 430 insertions, 4 deletions
diff --git a/apct-tests/perftests/core/Android.mk b/apct-tests/perftests/core/Android.mk index e9f18fd7d0ec..2fd6740e5719 100644 --- a/apct-tests/perftests/core/Android.mk +++ b/apct-tests/perftests/core/Android.mk @@ -3,6 +3,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := android-support-test apct-perftests-utils diff --git a/apct-tests/perftests/core/res/layout/test_linear_layout.xml b/apct-tests/perftests/core/res/layout/test_linear_layout.xml new file mode 100644 index 000000000000..a863d1b51d05 --- /dev/null +++ b/apct-tests/perftests/core/res/layout/test_linear_layout.xml @@ -0,0 +1,87 @@ +<!-- + Copyright (C) 2016 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" > + + <ImageButton + android:id="@+id/button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> + + <ImageButton + android:id="@+id/button2" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" /> + + <LinearLayout + 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 + 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>
\ No newline at end of file diff --git a/apct-tests/perftests/core/res/layout/test_linear_layout_weighted.xml b/apct-tests/perftests/core/res/layout/test_linear_layout_weighted.xml new file mode 100644 index 000000000000..77a982c5c54f --- /dev/null +++ b/apct-tests/perftests/core/res/layout/test_linear_layout_weighted.xml @@ -0,0 +1,89 @@ +<!-- + Copyright (C) 2016 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_weighted_root" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="10dp" > + + <ImageButton + android:id="@+id/button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> + + <ImageButton + android:id="@+id/button2" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" /> + + <LinearLayout + 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_weight="2" + android:layout_alignParentLeft="true" + android:layout_centerVertical="true" /> + + <LinearLayout + 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_weight="1" + 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>
\ No newline at end of file diff --git a/apct-tests/perftests/core/res/layout/test_relative_layout.xml b/apct-tests/perftests/core/res/layout/test_relative_layout.xml new file mode 100644 index 000000000000..1daf93aaaf07 --- /dev/null +++ b/apct-tests/perftests/core/res/layout/test_relative_layout.xml @@ -0,0 +1,87 @@ +<!-- + Copyright (C) 2016 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. +--> + +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/relative_layout_root" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="10dp" > + + <ImageButton + android:id="@+id/button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" /> + + <ImageButton + android:id="@+id/button2" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentRight="true" + android:layout_centerVertical="true" /> + + <RelativeLayout + 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" /> + + <RelativeLayout + 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" /> + </RelativeLayout> + + <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" /> + </RelativeLayout> + +</RelativeLayout>
\ No newline at end of file diff --git a/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java new file mode 100644 index 000000000000..db15e9bbe4b6 --- /dev/null +++ b/apct-tests/perftests/core/src/android/widget/LayoutPerfTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 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.widget; + +import android.app.Activity; +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.perftests.utils.StubActivity; +import android.support.test.annotation.UiThreadTest; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; +import android.view.View; +import android.view.ViewGroup; + +import com.android.core.frameworks.perftests.R; + +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.List; + +import static android.perftests.utils.LayoutUtils.gatherViewTree; +import static android.perftests.utils.LayoutUtils.requestLayoutForAllNodes; +import static android.view.View.MeasureSpec.AT_MOST; +import static android.view.View.MeasureSpec.EXACTLY; +import static android.view.View.MeasureSpec.UNSPECIFIED; + +@LargeTest +@RunWith(Parameterized.class) +public class LayoutPerfTest { + @Parameterized.Parameters(name = "{0}") + public static Collection measureSpecs() { + return Arrays.asList(new Object[][] { + { "relative", R.layout.test_relative_layout, R.id.relative_layout_root }, + { "linear", R.layout.test_linear_layout, R.id.linear_layout_root }, + { "linear_weighted", R.layout.test_linear_layout_weighted, + R.id.linear_layout_weighted_root }, + }); + } + + private int[] mMeasureSpecs = {EXACTLY, AT_MOST, UNSPECIFIED}; + + private int mLayoutId; + private int mViewId; + + public LayoutPerfTest(String key, int layoutId, int viewId) { + // key is used in the final report automatically. + mLayoutId = layoutId; + mViewId = viewId; + } + + @Rule + public ActivityTestRule<StubActivity> mActivityRule = + new ActivityTestRule(StubActivity.class); + + @Rule + public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + @UiThreadTest + public void testLayoutPerf() { + Activity activity = mActivityRule.getActivity(); + activity.setContentView(mLayoutId); + + ViewGroup viewGroup = (ViewGroup) activity.findViewById(mViewId); + + List<View> allNodes = gatherViewTree(viewGroup); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + + int length = mMeasureSpecs.length; + while (state.keepRunning()) { + for (int i = 0; i < length; i++) { + // The overhead of this call is ignorable, like within 1% difference. + requestLayoutForAllNodes(allNodes); + + viewGroup.measure(mMeasureSpecs[i % length], mMeasureSpecs[i % length]); + viewGroup.layout(0, 0, viewGroup.getMeasuredWidth(), viewGroup.getMeasuredHeight()); + } + } + } +} diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java index 2c5a9eac481d..4213e4a3aa2b 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java @@ -176,10 +176,15 @@ public class BenchmarkState { private String summaryLine() { StringBuilder sb = new StringBuilder(); sb.append("Summary: "); - sb.append("median=" + median() + "ns, "); - sb.append("mean=" + mean() + "ns, "); - sb.append("sigma=" + standardDeviation() + ", "); - sb.append("iteration=" + mResults.size()); + sb.append("median=").append(median()).append("ns, "); + sb.append("mean=").append(mean()).append("ns, "); + sb.append("sigma=").append(standardDeviation()).append(", "); + sb.append("iteration=").append(mResults.size()).append(", "); + // print out the first few iterations' number for double checking. + int sampleNumber = Math.min(mResults.size(), MIN_REPEAT_TIMES); + for (int i = 0; i < sampleNumber; i++) { + sb.append("No ").append(i).append(" result is ").append(mResults.get(i)).append(", "); + } return sb.toString(); } diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/LayoutUtils.java b/apct-tests/perftests/utils/src/android/perftests/utils/LayoutUtils.java new file mode 100644 index 000000000000..c64af8fccb36 --- /dev/null +++ b/apct-tests/perftests/utils/src/android/perftests/utils/LayoutUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 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.perftests.utils; + +import android.view.View; +import android.view.ViewGroup; + +import java.util.ArrayList; +import java.util.List; + +public class LayoutUtils { + + private static void recursivelyGather(ViewGroup currentNode, List<View> nodeList) { + nodeList.add(currentNode); + int count = currentNode.getChildCount(); + for (int i = 0; i < count; i++) { + View view = currentNode.getChildAt(i); + if (view instanceof ViewGroup) { + recursivelyGather((ViewGroup) view, nodeList); + } else { + nodeList.add(view); + } + } + } + + /** + * Flattern the whole view tree into a list of View. + */ + public static List<View> gatherViewTree(ViewGroup root) { + List<View> result = new ArrayList<View>(); + recursivelyGather(root, result); + return result; + } + + /** + * For every node in the list, call requestLayout. + */ + public static void requestLayoutForAllNodes(List<View> nodeList) { + int count = nodeList.size(); + for (int i = 0; i < count; i++) { + nodeList.get(i).requestLayout(); + } + } +} |