[tracing] Add sqlite memory statistics to tracing.

The process-wide memory usage statistics of sqlite library is added to
chrome://tracing. The memory usage of sqlite library is mainly through
sqlite_malloc. The total usage of the process is recorded by
sqlite3_memory_used() api. This CL also adds per-connection memory
usage to tracing. Each connection uses memory for cache, schema and
statement, and these usages are recorded. sqlit3_malloc uses malloc
internally to allocate memory. So, thie memory is traced as
sub-allocation from system_allocator(malloc).
This CL lets us keep track of sqlite memory usage in chrome telemetry.

BUG=466141

Review URL: https://codereview.chromium.org/1327063002

Cr-Commit-Position: refs/heads/master@{#353549}
diff --git a/sql/connection.cc b/sql/connection.cc
index 20f0f07..61aebbe 100644
--- a/sql/connection.cc
+++ b/sql/connection.cc
@@ -19,6 +19,8 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/process_memory_dump.h"
 #include "sql/statement.h"
 #include "third_party/sqlite/sqlite3.h"
 
@@ -217,6 +219,44 @@
   return current_ignorer_cb_->Run(error);
 }
 
+bool Connection::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+                              base::trace_event::ProcessMemoryDump* pmd) {
+  if (args.level_of_detail ==
+          base::trace_event::MemoryDumpLevelOfDetail::LIGHT ||
+      !db_) {
+    return true;
+  }
+
+  // The high water mark is not tracked for the following usages.
+  int cache_size, dummy_int;
+  sqlite3_db_status(db_, SQLITE_DBSTATUS_CACHE_USED, &cache_size, &dummy_int,
+                    0 /* resetFlag */);
+  int schema_size;
+  sqlite3_db_status(db_, SQLITE_DBSTATUS_SCHEMA_USED, &schema_size, &dummy_int,
+                    0 /* resetFlag */);
+  int statement_size;
+  sqlite3_db_status(db_, SQLITE_DBSTATUS_STMT_USED, &statement_size, &dummy_int,
+                    0 /* resetFlag */);
+
+  std::string name = base::StringPrintf(
+      "sqlite/%s_connection/%p",
+      histogram_tag_.empty() ? "Unknown" : histogram_tag_.c_str(), this);
+  base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(name);
+  dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+                  base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                  cache_size + schema_size + statement_size);
+  dump->AddScalar("cache_size",
+                  base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                  cache_size);
+  dump->AddScalar("schema_size",
+                  base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                  schema_size);
+  dump->AddScalar("statement_size",
+                  base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+                  statement_size);
+  return true;
+}
+
 // static
 void Connection::SetErrorIgnorer(Connection::ErrorIgnorerCallback* cb) {
   CHECK(current_ignorer_cb_ == NULL);
@@ -291,9 +331,13 @@
       update_time_histogram_(NULL),
       query_time_histogram_(NULL),
       clock_(new TimeSource()) {
+  base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+      this);
 }
 
 Connection::~Connection() {
+  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+      this);
   Close();
 }