Chromium Code Reviews| Index: sync/syncable/directory.cc |
| diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc |
| index ca1efc1c95bda86f708e288e667e15b106d39b25..a93fdea808eb669cb0036422303309627d948db6 100644 |
| --- a/sync/syncable/directory.cc |
| +++ b/sync/syncable/directory.cc |
| @@ -4,6 +4,7 @@ |
| #include "sync/syncable/directory.h" |
| +#include <inttypes.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| @@ -16,10 +17,14 @@ |
| #include "base/metrics/histogram.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| +#include "base/strings/stringprintf.h" |
| +#include "base/trace_event/memory_dump_manager.h" |
| +#include "base/trace_event/process_memory_dump.h" |
| #include "base/trace_event/trace_event.h" |
| #include "sync/internal_api/public/base/attachment_id_proto.h" |
| #include "sync/internal_api/public/base/unique_position.h" |
| #include "sync/internal_api/public/util/unrecoverable_error_handler.h" |
| +#include "sync/protocol/proto_value_conversions.h" |
| #include "sync/syncable/entry.h" |
| #include "sync/syncable/entry_kernel.h" |
| #include "sync/syncable/in_memory_directory_backing_store.h" |
| @@ -39,6 +44,18 @@ using std::string; |
| namespace syncer { |
| namespace syncable { |
| +namespace { |
| + |
| +template <typename Key, typename Value> |
| +size_t GetUnorderedMapMemoryUsage(const std::unordered_map<Key, Value> map) { |
|
DmitrySkiba
2016/08/09 17:44:10
I think you missed & here: const std::unordered_ma
|
| + // Considers the hashtable to be an array of buckets which are linked list of |
| + // nodes. Each node contains a next pointer and the cached hash value. |
| + size_t node_size = sizeof(std::pair<Key, Value>) + 2 * sizeof(void*); |
| + size_t bucket_overhead = sizeof(void*); |
| + return map.bucket_count() * bucket_overhead + node_size * map.size(); |
| +} |
| +} |
| + |
| // static |
| const base::FilePath::CharType Directory::kSyncDatabaseFilename[] = |
| FILE_PATH_LITERAL("SyncData.sqlite3"); |
| @@ -215,6 +232,9 @@ DirOpenResult Directory::OpenImpl( |
| store_->SetCatastrophicErrorHandler(base::Bind( |
| &Directory::OnCatastrophicError, weak_ptr_factory_.GetWeakPtr())); |
| + UMA_HISTOGRAM_COUNTS("Sync.DirectoryMemoryUsageKB", |
| + GetApproximateMemoryUsage()); |
| + |
| return OPENED; |
| } |
| @@ -920,6 +940,108 @@ size_t Directory::GetEntriesCount() const { |
| return kernel_->metahandles_map.size(); |
| } |
| +size_t Directory::GetApproximateMemoryUsage() { |
| + size_t total = 0; |
| + ScopedKernelLock lock(this); |
| + total += sizeof(this) + GetUnorderedMapMemoryUsage(kernel_->metahandles_map) + |
| + GetUnorderedMapMemoryUsage(kernel_->ids_map) + |
| + GetUnorderedMapMemoryUsage(kernel_->server_tags_map) + |
| + GetUnorderedMapMemoryUsage(kernel_->client_tags_map) + |
| + GetUnorderedMapMemoryUsage(kernel_->index_by_attachment_id); |
| + total += kernel_->parent_child_index.MemoryUsage(); |
| + |
| + for (size_t i = 0; i < MODEL_TYPE_COUNT; ++i) |
| + total += |
| + kernel_->persisted_info.datatype_context[i].context().capacity() + 1; |
| + |
| + for (auto entry : kernel_->index_by_attachment_id) |
|
DmitrySkiba
2016/08/09 17:44:10
const auto&, all other places too.
|
| + total += entry.first.capacity() + 1 + entry.second.size() * sizeof(int64_t); |
| + |
| + for (auto entry : kernel_->ids_map) |
| + total += entry.first.capacity() + 1; |
| + |
| + for (auto handle : kernel_->metahandles_map) { |
| + // If entry was not changed after the last estimation, use the cached size. |
| + if (handle.second->cached_size()) { |
| + total += handle.second->cached_size(); |
| + continue; |
| + } |
| + |
| + size_t entry_size = 0; |
|
DmitrySkiba
2016/08/09 17:44:10
I think this whole thing should be moved into Entr
|
| + for (unsigned i = ID_FIELDS_BEGIN; i < ID_FIELDS_END; ++i) { |
| + entry_size += |
| + handle.second->ref(static_cast<IdField>(i)).value().capacity() + 1; |
| + } |
| + for (unsigned i = STRING_FIELDS_BEGIN; i < STRING_FIELDS_END; ++i) { |
| + if (i == UNIQUE_SERVER_TAG || i == UNIQUE_CLIENT_TAG) { |
| + // These are stored again in either |client_tags_map| or |
| + // |server_tags_map|. |
| + entry_size += |
| + 2 * |
| + (handle.second->ref(static_cast<StringField>(i)).capacity() + 1); |
| + } else { |
| + entry_size += |
| + handle.second->ref(static_cast<StringField>(i)).capacity() + 1; |
| + } |
| + } |
| + const sync_pb::EntitySpecifics* last_entity = nullptr; |
| + for (unsigned i = PROTO_FIELDS_BEGIN; i < PROTO_FIELDS_END; ++i) { |
| + const auto& field = handle.second->ref(static_cast<ProtoField>(i)); |
| + if (&sync_pb::EntitySpecifics::default_instance() != &field) { |
| + // Any two fields referencing to same entity are consecutive. Continue |
| + // if already accounted. |
| + if (last_entity == &field) |
| + continue; |
| + last_entity = &field; |
| + entry_size += GetEntitySpecificsSize(field); |
| + } else { |
| + last_entity = nullptr; |
| + } |
| + } |
| + const sync_pb::AttachmentMetadata* last_field = nullptr; |
| + for (unsigned i = ATTACHMENT_METADATA_FIELDS_BEGIN; |
| + i < ATTACHMENT_METADATA_FIELDS_END; ++i) { |
| + const auto& field = |
| + handle.second->ref(static_cast<AttachmentMetadataField>(i)); |
| + if (&sync_pb::AttachmentMetadata::default_instance() != &field) { |
| + if (last_field == &field) |
| + continue; |
| + last_field = &field; |
| + entry_size += sizeof(sync_pb::AttachmentMetadata); |
| + entry_size += |
| + field.record_size() * (sizeof(sync_pb::AttachmentMetadataRecord) + |
| + sizeof(sync_pb::AttachmentIdProto)); |
| + for (int i = 0; i < field.record_size(); ++i) |
| + entry_size += field.record(i).id().unique_id().capacity() + 1; |
| + } else { |
| + last_field = nullptr; |
| + } |
| + } |
| + for (unsigned i = UNIQUE_POSITION_FIELDS_BEGIN; |
| + i < UNIQUE_POSITION_FIELDS_END; ++i) { |
| + entry_size += handle.second->ref(static_cast<UniquePositionField>(i)) |
| + .compressed_byte_size(); |
| + } |
| + |
| + handle.second->set_cached_size(entry_size); |
| + total += entry_size; |
| + } |
| + return total; |
| +} |
| + |
| +void Directory::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) { |
| + auto dump = pmd->CreateAllocatorDump(base::StringPrintf( |
| + "sync/0x%" PRIXPTR, reinterpret_cast<uintptr_t>(this))); |
| + dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| + base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| + GetApproximateMemoryUsage()); |
| + 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); |
| +} |
| + |
| void Directory::SetDownloadProgress( |
| ModelType model_type, |
| const sync_pb::DataTypeProgressMarker& new_progress) { |