[tracing] Add support for skia caches to dump memory stats
Dump the memory statistics of resource cache and glyph cache using the
SkTraceMemoryDump interface.
BUG=chromium:503168
Review URL: https://codereview.chromium.org/1313793004
diff --git a/include/core/SkGraphics.h b/include/core/SkGraphics.h
index 8d804b3..8e8bd77 100644
--- a/include/core/SkGraphics.h
+++ b/include/core/SkGraphics.h
@@ -12,6 +12,7 @@
class SkData;
class SkImageGenerator;
+class SkTraceMemoryDump;
class SK_API SkGraphics {
public:
@@ -115,6 +116,12 @@
static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit);
/**
+ * Dumps memory usage of caches using the SkTraceMemoryDump interface. See SkTraceMemoryDump
+ * for usage of this method.
+ */
+ static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
+
+ /**
* Applications with command line options may pass optional state, such
* as cache sizes, here, for instance:
* font-cache-limit=12345678
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index e6d66f0..f83aab5 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -11,6 +11,7 @@
#include "SkLazyPtr.h"
#include "SkPath.h"
#include "SkTemplates.h"
+#include "SkTraceMemoryDump.h"
#include "SkTypeface.h"
//#define SPEW_PURGE_STATUS
@@ -19,6 +20,14 @@
SkGlyphCache_Globals* create_globals() { return new SkGlyphCache_Globals; }
+const char gGlyphCacheDumpName[] = "skia/sk_glyph_cache";
+
+// Used to pass context to the sk_trace_dump_visitor.
+struct SkGlyphCacheDumpContext {
+ int* counter;
+ SkTraceMemoryDump* dump;
+};
+
} // namespace
SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals);
@@ -424,6 +433,40 @@
SkGlyphCache::VisitAll(dump_visitor, &counter);
}
+static void sk_trace_dump_visitor(const SkGlyphCache& cache, void* context) {
+ SkGlyphCacheDumpContext* dumpContext = static_cast<SkGlyphCacheDumpContext*>(context);
+ SkTraceMemoryDump* dump = dumpContext->dump;
+ int* counter = dumpContext->counter;
+ int index = *counter;
+ *counter += 1;
+
+ const SkTypeface* face = cache.getScalerContext()->getTypeface();
+ SkString font_name;
+ face->getFamilyName(&font_name);
+ const SkScalerContextRec& rec = cache.getScalerContext()->getRec();
+
+ SkString dump_name = SkStringPrintf("%s/%s_%3d/index_%d",
+ gGlyphCacheDumpName, font_name.c_str(), rec.fFontID, index);
+
+ dump->dumpNumericValue(dump_name.c_str(), "size", "bytes", cache.getMemoryUsed());
+ dump->dumpNumericValue(dump_name.c_str(), "glyph_count", "objects", cache.countCachedGlyphs());
+ dump->setMemoryBacking(dump_name.c_str(), "malloc", nullptr);
+}
+
+void SkGlyphCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
+ dump->dumpNumericValue(gGlyphCacheDumpName, "size", "bytes", SkGraphics::GetFontCacheUsed());
+ dump->dumpNumericValue(gGlyphCacheDumpName, "budget_size", "bytes",
+ SkGraphics::GetFontCacheLimit());
+ dump->dumpNumericValue(gGlyphCacheDumpName, "glyph_count", "objects",
+ SkGraphics::GetFontCacheCountUsed());
+ dump->dumpNumericValue(gGlyphCacheDumpName, "budget_glyph_count", "objects",
+ SkGraphics::GetFontCacheCountLimit());
+
+ int counter = 0;
+ SkGlyphCacheDumpContext context = { &counter, dump };
+ SkGlyphCache::VisitAll(sk_trace_dump_visitor, &context);
+}
+
void SkGlyphCache::VisitAll(Visitor visitor, void* context) {
SkGlyphCache_Globals& globals = get_globals();
AutoAcquire ac(globals.fLock);
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index 7062041..2f1f417 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -17,6 +17,7 @@
#include "SkTDArray.h"
class SkPaint;
+class SkTraceMemoryDump;
class SkGlyphCache_Globals;
@@ -97,9 +98,12 @@
return fScalerContext->isSubpixel();
}
+ /** Return the approx RAM usage for this cache. */
+ size_t getMemoryUsed() const { return fMemoryUsed; }
+
void dump() const;
- /* AuxProc/Data allow a client to associate data with this cache entry. Multiple clients can
+ /** AuxProc/Data allow a client to associate data with this cache entry. Multiple clients can
use this, as their data is keyed with a function pointer. In addition to serving as a
key, the function pointer is called with the data when the glyphcache object is deleted,
so the client can cleanup their data as well.
@@ -141,6 +145,11 @@
static void Dump();
+ /** Dump memory usage statistics of all the attaches caches in the process using the
+ SkTraceMemoryDump interface.
+ */
+ static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
+
typedef void (*Visitor)(const SkGlyphCache&, void* context);
static void VisitAll(Visitor, void* context);
diff --git a/src/core/SkGraphics.cpp b/src/core/SkGraphics.cpp
index f8d8b09..e9dcadc 100644
--- a/src/core/SkGraphics.cpp
+++ b/src/core/SkGraphics.cpp
@@ -12,6 +12,7 @@
#include "SkBlitter.h"
#include "SkCanvas.h"
#include "SkGeometry.h"
+#include "SkGlyphCache.h"
#include "SkMath.h"
#include "SkMatrix.h"
#include "SkOpts.h"
@@ -19,6 +20,7 @@
#include "SkPathEffect.h"
#include "SkPixelRef.h"
#include "SkRefCnt.h"
+#include "SkResourceCache.h"
#include "SkRTConf.h"
#include "SkScalerContext.h"
#include "SkShader.h"
@@ -64,6 +66,13 @@
///////////////////////////////////////////////////////////////////////////////
+void SkGraphics::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
+ SkResourceCache::DumpMemoryStatistics(dump);
+ SkGlyphCache::DumpMemoryStatistics(dump);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
static const char kFontCacheLimitStr[] = "font-cache-limit";
static const size_t kFontCacheLimitLen = sizeof(kFontCacheLimitStr) - 1;
diff --git a/src/core/SkResourceCache.cpp b/src/core/SkResourceCache.cpp
index 4d2453c..7d3c342 100644
--- a/src/core/SkResourceCache.cpp
+++ b/src/core/SkResourceCache.cpp
@@ -11,6 +11,7 @@
#include "SkMutex.h"
#include "SkPixelRef.h"
#include "SkResourceCache.h"
+#include "SkTraceMemoryDump.h"
#include <stddef.h>
#include <stdlib.h>
@@ -669,3 +670,19 @@
void SkResourceCache::TestDumpMemoryStatistics() {
VisitAll(dump_visitor, nullptr);
}
+
+static void sk_trace_dump_visitor(const SkResourceCache::Rec& rec, void* context) {
+ SkTraceMemoryDump* dump = static_cast<SkTraceMemoryDump*>(context);
+ SkString dump_name = SkStringPrintf("skia/sk_resource_cache/%s_%p", rec.getCategory(), &rec);
+ SkDiscardableMemory* discardable = rec.diagnostic_only_getDiscardable();
+ if (discardable) {
+ dump->setDiscardableMemoryBacking(dump_name.c_str(), *discardable);
+ } else {
+ dump->dumpNumericValue(dump_name.c_str(), "size", "bytes", rec.bytesUsed());
+ dump->setMemoryBacking(dump_name.c_str(), "malloc", nullptr);
+ }
+}
+
+void SkResourceCache::DumpMemoryStatistics(SkTraceMemoryDump* dump) {
+ VisitAll(sk_trace_dump_visitor, dump);
+}
diff --git a/src/core/SkResourceCache.h b/src/core/SkResourceCache.h
index 813e2ee..a748133 100644
--- a/src/core/SkResourceCache.h
+++ b/src/core/SkResourceCache.h
@@ -14,6 +14,7 @@
class SkCachedData;
class SkDiscardableMemory;
+class SkTraceMemoryDump;
/**
* Cache object for bitmaps (with possible scale in X Y as part of the key).
@@ -152,6 +153,11 @@
static void TestDumpMemoryStatistics();
+ /** Dump memory usage statistics of every Rec in the cache using the
+ SkTraceMemoryDump interface.
+ */
+ static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
+
/**
* Returns the DiscardableFactory used by the global cache, or nullptr.
*/