diff options
-rw-r--r-- | apct-tests/perftests/core/res/layout/test_simple_view.xml | 20 | ||||
-rw-r--r-- | apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java | 31 | ||||
-rw-r--r-- | apct-tests/perftests/core/src/android/view/ViewPerfTest.java | 47 | ||||
-rw-r--r-- | apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java | 12 | ||||
-rw-r--r-- | core/java/android/view/RenderNode.java | 47 | ||||
-rw-r--r-- | core/java/android/view/SurfaceView.java | 1 | ||||
-rw-r--r-- | core/java/android/view/View.java | 7 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/Android.mk | 1 | ||||
-rw-r--r-- | libs/hwui/tests/microbench/RenderNodeBench.cpp | 33 |
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); + |