Merge "Improve dumping of display list memory usage"
This commit is contained in:
committed by
Android (Google) Code Review
commit
a36ebded5c
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -115,6 +115,7 @@ public:
|
||||
* wasted)
|
||||
*/
|
||||
size_t usedSize() const { return mTotalAllocated - mWastedSpace; }
|
||||
size_t allocatedSize() const { return mTotalAllocated; }
|
||||
|
||||
private:
|
||||
LinearAllocator(const LinearAllocator& other);
|
||||
|
||||
Reference in New Issue
Block a user