[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}
This commit is contained in:
@@ -71,6 +71,7 @@
|
|||||||
#include "net/ssl/ssl_config_service.h"
|
#include "net/ssl/ssl_config_service.h"
|
||||||
#include "ipc/mojo/scoped_ipc_support.h"
|
#include "ipc/mojo/scoped_ipc_support.h"
|
||||||
#include "skia/ext/skia_memory_dump_provider.h"
|
#include "skia/ext/skia_memory_dump_provider.h"
|
||||||
|
#include "sql/sql_memory_dump_provider.h"
|
||||||
#include "ui/base/clipboard/clipboard.h"
|
#include "ui/base/clipboard/clipboard.h"
|
||||||
|
|
||||||
#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
|
#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
|
||||||
@@ -661,6 +662,8 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
|
|||||||
HostSharedBitmapManager::current());
|
HostSharedBitmapManager::current());
|
||||||
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
|
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
|
||||||
skia::SkiaMemoryDumpProvider::GetInstance());
|
skia::SkiaMemoryDumpProvider::GetInstance());
|
||||||
|
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
|
||||||
|
sql::SqlMemoryDumpProvider::GetInstance());
|
||||||
|
|
||||||
#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
|
#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
|
||||||
trace_memory_controller_.reset(new base::trace_event::TraceMemoryController(
|
trace_memory_controller_.reset(new base::trace_event::TraceMemoryController(
|
||||||
|
@@ -15,6 +15,8 @@ component("sql") {
|
|||||||
"meta_table.h",
|
"meta_table.h",
|
||||||
"recovery.cc",
|
"recovery.cc",
|
||||||
"recovery.h",
|
"recovery.h",
|
||||||
|
"sql_memory_dump_provider.cc",
|
||||||
|
"sql_memory_dump_provider.h",
|
||||||
"statement.cc",
|
"statement.cc",
|
||||||
"statement.h",
|
"statement.h",
|
||||||
"transaction.cc",
|
"transaction.cc",
|
||||||
@@ -77,6 +79,7 @@ test("sql_unittests") {
|
|||||||
"connection_unittest.cc",
|
"connection_unittest.cc",
|
||||||
"meta_table_unittest.cc",
|
"meta_table_unittest.cc",
|
||||||
"recovery_unittest.cc",
|
"recovery_unittest.cc",
|
||||||
|
"sql_memory_dump_provider_unittest.cc",
|
||||||
"sqlite_features_unittest.cc",
|
"sqlite_features_unittest.cc",
|
||||||
"statement_unittest.cc",
|
"statement_unittest.cc",
|
||||||
"test/paths.cc",
|
"test/paths.cc",
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/synchronization/lock.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 "sql/statement.h"
|
||||||
#include "third_party/sqlite/sqlite3.h"
|
#include "third_party/sqlite/sqlite3.h"
|
||||||
|
|
||||||
@@ -217,6 +219,44 @@ bool Connection::ShouldIgnoreSqliteError(int error) {
|
|||||||
return current_ignorer_cb_->Run(error);
|
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
|
// static
|
||||||
void Connection::SetErrorIgnorer(Connection::ErrorIgnorerCallback* cb) {
|
void Connection::SetErrorIgnorer(Connection::ErrorIgnorerCallback* cb) {
|
||||||
CHECK(current_ignorer_cb_ == NULL);
|
CHECK(current_ignorer_cb_ == NULL);
|
||||||
@@ -291,9 +331,13 @@ Connection::Connection()
|
|||||||
update_time_histogram_(NULL),
|
update_time_histogram_(NULL),
|
||||||
query_time_histogram_(NULL),
|
query_time_histogram_(NULL),
|
||||||
clock_(new TimeSource()) {
|
clock_(new TimeSource()) {
|
||||||
|
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
|
||||||
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::~Connection() {
|
Connection::~Connection() {
|
||||||
|
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
|
||||||
|
this);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "base/threading/thread_restrictions.h"
|
#include "base/threading/thread_restrictions.h"
|
||||||
#include "base/time/time.h"
|
#include "base/time/time.h"
|
||||||
|
#include "base/trace_event/memory_dump_provider.h"
|
||||||
#include "sql/sql_export.h"
|
#include "sql/sql_export.h"
|
||||||
|
|
||||||
struct sqlite3;
|
struct sqlite3;
|
||||||
@@ -102,7 +103,7 @@ class SQL_EXPORT TimeSource {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(TimeSource);
|
DISALLOW_COPY_AND_ASSIGN(TimeSource);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SQL_EXPORT Connection {
|
class SQL_EXPORT Connection : public base::trace_event::MemoryDumpProvider {
|
||||||
private:
|
private:
|
||||||
class StatementRef; // Forward declaration, see real one below.
|
class StatementRef; // Forward declaration, see real one below.
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ class SQL_EXPORT Connection {
|
|||||||
// The database is opened by calling Open[InMemory](). Any uncommitted
|
// The database is opened by calling Open[InMemory](). Any uncommitted
|
||||||
// transactions will be rolled back when this object is deleted.
|
// transactions will be rolled back when this object is deleted.
|
||||||
Connection();
|
Connection();
|
||||||
~Connection();
|
~Connection() override;
|
||||||
|
|
||||||
// Pre-init configuration ----------------------------------------------------
|
// Pre-init configuration ----------------------------------------------------
|
||||||
|
|
||||||
@@ -464,6 +465,11 @@ class SQL_EXPORT Connection {
|
|||||||
// tests.
|
// tests.
|
||||||
static bool ShouldIgnoreSqliteError(int error);
|
static bool ShouldIgnoreSqliteError(int error);
|
||||||
|
|
||||||
|
// base::trace_event::MemoryDumpProvider implementation.
|
||||||
|
bool OnMemoryDump(
|
||||||
|
const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* process_memory_dump) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For recovery module.
|
// For recovery module.
|
||||||
friend class Recovery;
|
friend class Recovery;
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include "base/metrics/statistics_recorder.h"
|
#include "base/metrics/statistics_recorder.h"
|
||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
#include "base/test/histogram_tester.h"
|
#include "base/test/histogram_tester.h"
|
||||||
|
#include "base/trace_event/process_memory_dump.h"
|
||||||
#include "sql/connection.h"
|
#include "sql/connection.h"
|
||||||
#include "sql/correct_sql_test_base.h"
|
#include "sql/correct_sql_test_base.h"
|
||||||
#include "sql/meta_table.h"
|
#include "sql/meta_table.h"
|
||||||
@@ -1378,4 +1379,12 @@ TEST_F(SQLConnectionTest, MmapTest) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST_F(SQLConnectionTest, OnMemoryDump) {
|
||||||
|
base::trace_event::ProcessMemoryDump pmd(nullptr);
|
||||||
|
base::trace_event::MemoryDumpArgs args = {
|
||||||
|
base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
|
||||||
|
ASSERT_TRUE(db().OnMemoryDump(args, &pmd));
|
||||||
|
EXPECT_GE(pmd.allocator_dumps().size(), 1u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
'meta_table.h',
|
'meta_table.h',
|
||||||
'recovery.cc',
|
'recovery.cc',
|
||||||
'recovery.h',
|
'recovery.h',
|
||||||
|
'sql_memory_dump_provider.cc',
|
||||||
|
'sql_memory_dump_provider.h',
|
||||||
'statement.cc',
|
'statement.cc',
|
||||||
'statement.h',
|
'statement.h',
|
||||||
'transaction.cc',
|
'transaction.cc',
|
||||||
@@ -89,6 +91,7 @@
|
|||||||
'connection_unittest.cc',
|
'connection_unittest.cc',
|
||||||
'meta_table_unittest.cc',
|
'meta_table_unittest.cc',
|
||||||
'recovery_unittest.cc',
|
'recovery_unittest.cc',
|
||||||
|
'sql_memory_dump_provider_unittest.cc',
|
||||||
'sqlite_features_unittest.cc',
|
'sqlite_features_unittest.cc',
|
||||||
'statement_unittest.cc',
|
'statement_unittest.cc',
|
||||||
'test/paths.cc',
|
'test/paths.cc',
|
||||||
|
62
sql/sql_memory_dump_provider.cc
Normal file
62
sql/sql_memory_dump_provider.cc
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "sql/sql_memory_dump_provider.h"
|
||||||
|
|
||||||
|
#include "base/trace_event/memory_dump_manager.h"
|
||||||
|
#include "base/trace_event/process_memory_dump.h"
|
||||||
|
#include "third_party/sqlite/sqlite3.h"
|
||||||
|
|
||||||
|
namespace sql {
|
||||||
|
|
||||||
|
// static
|
||||||
|
SqlMemoryDumpProvider* SqlMemoryDumpProvider::GetInstance() {
|
||||||
|
return base::Singleton<
|
||||||
|
SqlMemoryDumpProvider,
|
||||||
|
base::LeakySingletonTraits<SqlMemoryDumpProvider>>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
SqlMemoryDumpProvider::SqlMemoryDumpProvider() {}
|
||||||
|
|
||||||
|
SqlMemoryDumpProvider::~SqlMemoryDumpProvider() {}
|
||||||
|
|
||||||
|
bool SqlMemoryDumpProvider::OnMemoryDump(
|
||||||
|
const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* pmd) {
|
||||||
|
int memory_used = 0;
|
||||||
|
int memory_high_water = 0;
|
||||||
|
int status = sqlite3_status(SQLITE_STATUS_MEMORY_USED, &memory_used,
|
||||||
|
&memory_high_water, 1 /*resetFlag */);
|
||||||
|
if (status != SQLITE_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
base::trace_event::MemoryAllocatorDump* dump =
|
||||||
|
pmd->CreateAllocatorDump("sqlite");
|
||||||
|
dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
|
||||||
|
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
|
||||||
|
memory_used);
|
||||||
|
dump->AddScalar("malloc_high_wmark_size",
|
||||||
|
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
|
||||||
|
memory_high_water);
|
||||||
|
|
||||||
|
int dummy_high_water = -1;
|
||||||
|
int malloc_count = -1;
|
||||||
|
status = sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &malloc_count,
|
||||||
|
&dummy_high_water, 0 /* resetFlag */);
|
||||||
|
if (status == SQLITE_OK) {
|
||||||
|
dump->AddScalar("malloc_count",
|
||||||
|
base::trace_event::MemoryAllocatorDump::kUnitsObjects,
|
||||||
|
malloc_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* system_allocator_name =
|
||||||
|
base::trace_event::MemoryDumpManager::GetInstance()
|
||||||
|
->system_allocator_pool_name();
|
||||||
|
if (system_allocator_name) {
|
||||||
|
pmd->AddSuballocation(dump->guid(), system_allocator_name);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sql
|
36
sql/sql_memory_dump_provider.h
Normal file
36
sql/sql_memory_dump_provider.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef SQL_PROCESS_MEMORY_DUMP_PROVIDER_H
|
||||||
|
#define SQL_PROCESS_MEMORY_DUMP_PROVIDER_H
|
||||||
|
|
||||||
|
#include "base/memory/singleton.h"
|
||||||
|
#include "base/trace_event/memory_dump_provider.h"
|
||||||
|
#include "sql/sql_export.h"
|
||||||
|
|
||||||
|
namespace sql {
|
||||||
|
|
||||||
|
// Adds process-wide memory usage statistics about sqlite to chrome://tracing.
|
||||||
|
// sql::Connection::OnMemoryDump adds per-connection memory statistics.
|
||||||
|
class SQL_EXPORT SqlMemoryDumpProvider
|
||||||
|
: public base::trace_event::MemoryDumpProvider {
|
||||||
|
public:
|
||||||
|
static SqlMemoryDumpProvider* GetInstance();
|
||||||
|
|
||||||
|
// MemoryDumpProvider implementation.
|
||||||
|
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* pmd) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend struct base::DefaultSingletonTraits<SqlMemoryDumpProvider>;
|
||||||
|
|
||||||
|
SqlMemoryDumpProvider();
|
||||||
|
~SqlMemoryDumpProvider() override;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(SqlMemoryDumpProvider);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sql
|
||||||
|
|
||||||
|
#endif // SQL_PROCESS_MEMORY_DUMP_PROVIDER_H
|
22
sql/sql_memory_dump_provider_unittest.cc
Normal file
22
sql/sql_memory_dump_provider_unittest.cc
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "sql/sql_memory_dump_provider.h"
|
||||||
|
|
||||||
|
#include "base/trace_event/process_memory_dump.h"
|
||||||
|
#include "sql/test/sql_test_base.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using SQLMemoryDumpProviderTest = sql::SQLTestBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SQLMemoryDumpProviderTest, OnMemoryDump) {
|
||||||
|
base::trace_event::ProcessMemoryDump pmd(nullptr);
|
||||||
|
base::trace_event::MemoryDumpArgs args = {
|
||||||
|
base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
|
||||||
|
ASSERT_TRUE(
|
||||||
|
sql::SqlMemoryDumpProvider::GetInstance()->OnMemoryDump(args, &pmd));
|
||||||
|
ASSERT_TRUE(pmd.GetAllocatorDump("sqlite"));
|
||||||
|
}
|
Reference in New Issue
Block a user