diff options
author | 2019-10-09 13:41:18 -0700 | |
---|---|---|
committer | 2019-10-09 13:42:43 -0700 | |
commit | 183e1380cef0f63610497abed01e16036a2ea2d4 (patch) | |
tree | 6be42299bdadf7fae5aaf58f787070123c6371aa | |
parent | 3441faa0453907f8713ebccfa33049c2e99e4fe6 (diff) |
Improve dumping of display list memory usage
The first step of improving is measuring. So measure better.
Bug: 138856108
Test: dump
Change-Id: I076b904a1f0dfb209622c76bcb8778a10cd2b7db
-rw-r--r-- | core/java/android/view/View.java | 3 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 36 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerGlobal.java | 22 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 12 | ||||
-rw-r--r-- | graphics/java/android/graphics/RenderNode.java | 20 | ||||
-rw-r--r-- | libs/hwui/RecordingCanvas.h | 1 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 14 | ||||
-rw-r--r-- | libs/hwui/RenderNode.h | 3 | ||||
-rw-r--r-- | libs/hwui/pipeline/skia/SkiaDisplayList.h | 1 | ||||
-rw-r--r-- | libs/hwui/utils/LinearAllocator.h | 1 |
10 files changed, 83 insertions, 30 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index cfb6a79a674c..c5d0a9b0a335 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -4496,8 +4496,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * When non-null and valid, this is expected to contain an up-to-date copy * of the background drawable. It is cleared on temporary detach, and reset * on cleanup. + * @hide */ - private RenderNode mBackgroundRenderNode; + RenderNode mBackgroundRenderNode; @UnsupportedAppUsage private int mBackgroundResource; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index fedd6fbe56ed..cf0698575851 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7297,26 +7297,42 @@ public final class ViewRootImpl implements ViewParent, } } - public void dumpGfxInfo(int[] info) { - info[0] = info[1] = 0; - if (mView != null) { - getGfxInfo(mView, info); + static final class GfxInfo { + public int viewCount; + public long renderNodeMemoryUsage; + public long renderNodeMemoryAllocated; + + void add(GfxInfo other) { + viewCount += other.viewCount; + renderNodeMemoryUsage += other.renderNodeMemoryUsage; + renderNodeMemoryAllocated += other.renderNodeMemoryAllocated; } } - private static void getGfxInfo(View view, int[] info) { - RenderNode renderNode = view.mRenderNode; - info[0]++; - if (renderNode != null) { - info[1] += (int) renderNode.computeApproximateMemoryUsage(); + GfxInfo getGfxInfo() { + GfxInfo info = new GfxInfo(); + if (mView != null) { + appendGfxInfo(mView, info); } + return info; + } + + private static void computeRenderNodeUsage(RenderNode node, GfxInfo info) { + if (node == null) return; + info.renderNodeMemoryUsage += node.computeApproximateMemoryUsage(); + info.renderNodeMemoryAllocated += node.computeApproximateMemoryAllocated(); + } + private static void appendGfxInfo(View view, GfxInfo info) { + info.viewCount++; + computeRenderNodeUsage(view.mRenderNode, info); + computeRenderNodeUsage(view.mBackgroundRenderNode, info); if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; int count = group.getChildCount(); for (int i = 0; i < count; i++) { - getGfxInfo(group.getChildAt(i), info); + appendGfxInfo(group.getChildAt(i), info); } } } diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index 379acbecb613..55b2a2a4033a 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -604,26 +604,24 @@ public final class WindowManagerGlobal { pw.println("\nView hierarchy:\n"); - int viewsCount = 0; - int displayListsSize = 0; - int[] info = new int[2]; + ViewRootImpl.GfxInfo totals = new ViewRootImpl.GfxInfo(); for (int i = 0; i < count; i++) { ViewRootImpl root = mRoots.get(i); - root.dumpGfxInfo(info); + ViewRootImpl.GfxInfo info = root.getGfxInfo(); + totals.add(info); String name = getWindowName(root); - pw.printf(" %s\n %d views, %.2f kB of display lists", - name, info[0], info[1] / 1024.0f); + pw.printf(" %s\n %d views, %.2f kB of render nodes", + name, info.viewCount, info.renderNodeMemoryUsage / 1024.f); pw.printf("\n\n"); - - viewsCount += info[0]; - displayListsSize += info[1]; } - pw.printf("\nTotal ViewRootImpl: %d\n", count); - pw.printf("Total Views: %d\n", viewsCount); - pw.printf("Total DisplayList: %.2f kB\n\n", displayListsSize / 1024.0f); + pw.printf("\nTotal %-15s: %d\n", "ViewRootImpl", count); + pw.printf("Total %-15s: %d\n", "attached Views", totals.viewCount); + pw.printf("Total %-15s: %.2f kB (used) / %.2f kB (capacity)\n\n", "RenderNode", + totals.renderNodeMemoryUsage / 1024.0f, + totals.renderNodeMemoryAllocated / 1024.0f); } } finally { pw.flush(); diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 222a87321aa4..538861e21d96 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -52,9 +52,14 @@ static void android_view_RenderNode_output(JNIEnv* env, jobject clazz, jlong ren renderNode->output(); } -static jint android_view_RenderNode_getDebugSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) { +static jint android_view_RenderNode_getUsageSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); - return renderNode->getDebugSize(); + return renderNode->getUsageSize(); +} + +static jint android_view_RenderNode_getAllocatedSize(JNIEnv* env, jobject clazz, jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + return renderNode->getAllocatedSize(); } static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) { @@ -647,7 +652,8 @@ static const JNINativeMethod gMethods[] = { { "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create }, { "nGetNativeFinalizer", "()J", (void*) android_view_RenderNode_getNativeFinalizer }, { "nOutput", "(J)V", (void*) android_view_RenderNode_output }, - { "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize }, + { "nGetUsageSize", "(J)I", (void*) android_view_RenderNode_getUsageSize }, + { "nGetAllocatedSize", "(J)I", (void*) android_view_RenderNode_getAllocatedSize }, { "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator }, { "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators }, { "nRequestPositionUpdates", "(JLandroid/graphics/RenderNode$PositionUpdateListener;)V", (void*) android_view_RenderNode_requestPositionUpdates }, diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java index 0e635c774c84..17e3b4465130 100644 --- a/graphics/java/android/graphics/RenderNode.java +++ b/graphics/java/android/graphics/RenderNode.java @@ -1380,7 +1380,22 @@ public final class RenderNode { * @return Approximate memory usage in bytes. */ public @BytesLong long computeApproximateMemoryUsage() { - return nGetDebugSize(mNativeRenderNode); + return nGetUsageSize(mNativeRenderNode); + } + + /** + * Gets the approximate amount of memory allocated for the RenderNode for debug purposes. + * Does not include the memory allocated by any child RenderNodes nor any bitmaps, only the + * memory allocated for this RenderNode and any data it owns. + * + * The difference between this and {@link #computeApproximateMemoryUsage()} is this includes + * memory allocated but not used. In particular structures such as DisplayLists are similar + * to things like ArrayLists - they need to resize as commands are added to them. As such, + * memory used can be less than memory allocated. + * + * @hide */ + public @BytesLong long computeApproximateMemoryAllocated() { + return nGetAllocatedSize(mNativeRenderNode); } /** @@ -1485,7 +1500,8 @@ public final class RenderNode { private static native void nOutput(long renderNode); - private static native int nGetDebugSize(long renderNode); + private static native int nGetUsageSize(long renderNode); + private static native int nGetAllocatedSize(long renderNode); private static native void nRequestPositionUpdates(long renderNode, PositionUpdateListener callback); diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index a79b7c00ba04..322eff24dd34 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -69,6 +69,7 @@ public: bool hasText() const { return mHasText; } size_t usedSize() const { return fUsed; } + size_t allocatedSize() const { return fReserved; } private: friend class RecordingCanvas; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 8eb5e3d3dfbc..6761435a8171 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -108,7 +108,7 @@ void RenderNode::output(std::ostream& output, uint32_t level) { output << std::endl; } -int RenderNode::getDebugSize() { +int RenderNode::getUsageSize() { int size = sizeof(RenderNode); if (mStagingDisplayList) { size += mStagingDisplayList->getUsedSize(); @@ -119,6 +119,18 @@ int RenderNode::getDebugSize() { return size; } +int RenderNode::getAllocatedSize() { + int size = sizeof(RenderNode); + if (mStagingDisplayList) { + size += mStagingDisplayList->getAllocatedSize(); + } + if (mDisplayList && mDisplayList != mStagingDisplayList) { + size += mDisplayList->getAllocatedSize(); + } + return size; +} + + void RenderNode::prepareTree(TreeInfo& info) { ATRACE_CALL(); LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing"); diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index c6db7f1ba60d..d55e5b0ce836 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -102,7 +102,8 @@ public: ANDROID_API void setStagingDisplayList(DisplayList* newData); ANDROID_API void output(); - ANDROID_API int getDebugSize(); + ANDROID_API int getUsageSize(); + ANDROID_API int getAllocatedSize(); bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); } diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index e3c3273a726a..cdd00db9afdc 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -47,6 +47,7 @@ class FunctorDrawable; class SkiaDisplayList { public: size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); } + size_t getAllocatedSize() { return allocator.allocatedSize() + mDisplayList.allocatedSize(); } ~SkiaDisplayList() { /* Given that we are using a LinearStdAllocator to store some of the diff --git a/libs/hwui/utils/LinearAllocator.h b/libs/hwui/utils/LinearAllocator.h index 9c4a1be4b269..539e6544ef02 100644 --- a/libs/hwui/utils/LinearAllocator.h +++ b/libs/hwui/utils/LinearAllocator.h @@ -115,6 +115,7 @@ public: * wasted) */ size_t usedSize() const { return mTotalAllocated - mWastedSpace; } + size_t allocatedSize() const { return mTotalAllocated; } private: LinearAllocator(const LinearAllocator& other); |