[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.
      */