summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/res/layout/test_simple_view.xml20
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java31
-rw-r--r--apct-tests/perftests/core/src/android/view/ViewPerfTest.java47
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java12
-rw-r--r--core/java/android/view/RenderNode.java47
-rw-r--r--core/java/android/view/SurfaceView.java1
-rw-r--r--core/java/android/view/View.java7
-rw-r--r--core/jni/android_view_RenderNode.cpp5
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/tests/microbench/RenderNodeBench.cpp33
10 files changed, 178 insertions, 26 deletions
diff --git a/apct-tests/perftests/core/res/layout/test_simple_view.xml b/apct-tests/perftests/core/res/layout/test_simple_view.xml
new file mode 100644
index 000000000000..9bc29a81eb96
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/test_simple_view.xml
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/simple_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index 19047d3fa165..922a47542020 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -31,11 +31,38 @@ public class RenderNodePerfTest {
@Test
public void testMeasureRenderNodeJniOverhead() {
- RenderNode node = RenderNode.create("benchmark", null);
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final RenderNode node = RenderNode.create("benchmark", null);
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
node.setTranslationX(1.0f);
}
}
+
+ @Test
+ public void testCreateRenderNodeNoName() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ RenderNode node = RenderNode.create(null, null);
+ node.destroy();
+ }
+ }
+
+ @Test
+ public void testCreateRenderNode() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ RenderNode node = RenderNode.create("LinearLayout", null);
+ node.destroy();
+ }
+ }
+
+ @Test
+ public void testIsValid() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ RenderNode node = RenderNode.create("LinearLayout", null);
+ while (state.keepRunning()) {
+ node.isValid();
+ }
+ }
}
diff --git a/apct-tests/perftests/core/src/android/view/ViewPerfTest.java b/apct-tests/perftests/core/src/android/view/ViewPerfTest.java
new file mode 100644
index 000000000000..5503ca94134e
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/view/ViewPerfTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.widget.FrameLayout;
+
+import com.android.perftests.core.R;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class ViewPerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void testSimpleViewInflate() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ LayoutInflater inflater = LayoutInflater.from(context);
+ FrameLayout root = new FrameLayout(context);
+ while (state.keepRunning()) {
+ inflater.inflate(R.layout.test_simple_view, root, false);
+ }
+ }
+}
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 519d5248a347..fd393e9d070c 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -19,8 +19,11 @@ package android.perftests.utils;
import android.app.Activity;
import android.app.Instrumentation;
import android.os.Bundle;
+import android.os.Debug;
+import android.support.test.InstrumentationRegistry;
import android.util.Log;
+import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@@ -45,6 +48,7 @@ import java.util.concurrent.TimeUnit;
public final class BenchmarkState {
private static final String TAG = "BenchmarkState";
+ private static final boolean ENABLE_PROFILING = false;
private static final int NOT_STARTED = 0; // The benchmark has not started yet.
private static final int WARMUP = 1; // The benchmark is warming up.
@@ -146,6 +150,11 @@ public final class BenchmarkState {
}
private void beginBenchmark(long warmupDuration, int iterations) {
+ if (ENABLE_PROFILING) {
+ File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof");
+ Log.d(TAG, "Tracing to: " + f.getAbsolutePath());
+ Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100);
+ }
mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
@@ -161,6 +170,9 @@ public final class BenchmarkState {
mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
mRepeatCount++;
if (mRepeatCount >= REPEAT_COUNT) {
+ if (ENABLE_PROFILING) {
+ Debug.stopMethodTracing();
+ }
calculateSatistics();
mState = FINISHED;
return false;
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 51d818b5f68d..7a3c95e004c5 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -26,8 +26,6 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import dalvik.annotation.optimization.FastNative;
-import libcore.util.NativeAllocationRegistry;
-
/**
* <p>A display list records a series of graphics related operations and can replay
* them later. Display lists are usually built by recording operations on a
@@ -132,36 +130,46 @@ import libcore.util.NativeAllocationRegistry;
*/
public class RenderNode {
- // Use a Holder to allow static initialization in the boot image.
- private static class NoImagePreloadHolder {
- public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024);
- }
-
private boolean mValid;
// Do not access directly unless you are ThreadedRenderer
- final long mNativeRenderNode;
+ long mNativeRenderNode;
private final View mOwningView;
private RenderNode(String name, View owningView) {
mNativeRenderNode = nCreate(name);
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
mOwningView = owningView;
- if (mOwningView instanceof SurfaceView) {
- nRequestPositionUpdates(mNativeRenderNode, (SurfaceView) mOwningView);
- }
}
/**
* @see RenderNode#adopt(long)
*/
private RenderNode(long nativePtr) {
- NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, nativePtr);
mNativeRenderNode = nativePtr;
mOwningView = null;
}
/**
+ * Immediately destroys the RenderNode
+ * Only suitable for testing/benchmarking where waiting for the GC/finalizer
+ * is not feasible.
+ */
+ public void destroy() {
+ if (mNativeRenderNode != 0) {
+ nFinalize(mNativeRenderNode);
+ mNativeRenderNode = 0;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
* Creates a new RenderNode that can be used to record batches of
* drawing operations, and store / apply render properties when drawn.
*
@@ -183,6 +191,13 @@ public class RenderNode {
return new RenderNode(nativePtr);
}
+ /**
+ * Enable callbacks for position changes.
+ */
+ public void requestPositionUpdates(SurfaceView view) {
+ nRequestPositionUpdates(mNativeRenderNode, view);
+ }
+
/**
* Starts recording a display list for the render node. All
@@ -784,9 +799,6 @@ public class RenderNode {
*/
void onRenderNodeDetached() {
discardDisplayList();
- if (mOwningView != null) {
- mOwningView.onRenderNodeDetached(this);
- }
}
///////////////////////////////////////////////////////////////////////////
@@ -823,6 +835,7 @@ public class RenderNode {
// Intentionally not static because it acquires a reference to 'this'
private native long nCreate(String name);
+ private native void nFinalize(long renderNode);
private static native long nGetNativeFinalizer();
private static native void nSetDisplayList(long renderNode, long newData);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5c56ebc47d27..d46910c2139c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -207,6 +207,7 @@ public class SurfaceView extends View {
public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mRenderNode.requestPositionUpdates(this);
setWillNotDraw(true);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20876a94bfc2..556072ef1eed 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16186,13 +16186,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Called when the passed RenderNode is removed from the draw tree
- * @hide
- */
- public void onRenderNodeDetached(RenderNode renderNode) {
- }
-
- /**
* <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
*
* @return A non-scaled bitmap representing this view or null if cache is disabled.
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index dd2a7a98b7a0..f88de51a9a12 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -124,6 +124,10 @@ static void releaseRenderNode(RenderNode* renderNode) {
renderNode->decStrong(0);
}
+static void android_view_RenderNode_finalize(JNIEnv* env, jobject clazz, jlong renderNodePtr) {
+ releaseRenderNode(reinterpret_cast<RenderNode*>(renderNodePtr));
+}
+
static jlong android_view_RenderNode_getNativeFinalizer(JNIEnv* env,
jobject clazz) {
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&releaseRenderNode));
@@ -650,6 +654,7 @@ static const JNINativeMethod gMethods[] = {
// Regular JNI
// ----------------------------------------------------------------------------
{ "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
+ { "nFinalize", "(J)V", (void*) android_view_RenderNode_finalize },
{ "nGetNativeFinalizer", "()J", (void*) android_view_RenderNode_getNativeFinalizer },
{ "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
{ "nOutput", "(J)V", (void*) android_view_RenderNode_output },
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 4fe866f2b5aa..67bcbcc15fbb 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -349,6 +349,7 @@ LOCAL_SRC_FILES += \
tests/microbench/FrameBuilderBench.cpp \
tests/microbench/LinearAllocatorBench.cpp \
tests/microbench/PathParserBench.cpp \
+ tests/microbench/RenderNodeBench.cpp \
tests/microbench/ShadowBench.cpp \
tests/microbench/TaskManagerBench.cpp
diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp
new file mode 100644
index 000000000000..a5bed0026b1c
--- /dev/null
+++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#include <benchmark/benchmark.h>
+
+#include "RenderNode.h"
+
+using namespace android;
+using namespace android::uirenderer;
+
+void BM_RenderNode_create(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ auto node = new RenderNode();
+ node->incStrong(0);
+ benchmark::DoNotOptimize(node);
+ node->decStrong(0);
+ }
+}
+BENCHMARK(BM_RenderNode_create);
+