1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/memory/shared_memory_tracker.h"
#include "base/check.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/base_tracing.h"
#include "base/tracing_buildflags.h"
#if BUILDFLAG(ENABLE_BASE_TRACING)
#include "base/trace_event/memory_dump_manager.h" // no-presubmit-check
#include "base/trace_event/process_memory_dump.h" // no-presubmit-check
#include "third_party/abseil-cpp/absl/types/optional.h"
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
namespace base {
const char SharedMemoryTracker::kDumpRootName[] = "shared_memory";
// static
SharedMemoryTracker* SharedMemoryTracker::GetInstance() {
static SharedMemoryTracker* instance = new SharedMemoryTracker;
return instance;
}
// static
std::string SharedMemoryTracker::GetDumpNameForTracing(
const UnguessableToken& id) {
DCHECK(!id.is_empty());
return std::string(kDumpRootName) + "/" + id.ToString();
}
// static
trace_event::MemoryAllocatorDumpGuid
SharedMemoryTracker::GetGlobalDumpIdForTracing(const UnguessableToken& id) {
std::string dump_name = GetDumpNameForTracing(id);
return trace_event::MemoryAllocatorDumpGuid(dump_name);
}
const trace_event::MemoryAllocatorDump*
SharedMemoryTracker::GetOrCreateSharedMemoryDump(
const SharedMemoryMapping& shared_memory,
trace_event::ProcessMemoryDump* pmd) {
return GetOrCreateSharedMemoryDumpInternal(shared_memory.raw_memory_ptr(),
shared_memory.mapped_size(),
shared_memory.guid(), pmd);
}
void SharedMemoryTracker::IncrementMemoryUsage(
const SharedMemoryMapping& mapping) {
AutoLock hold(usages_lock_);
DCHECK(usages_.find(mapping.raw_memory_ptr()) == usages_.end());
usages_.emplace(mapping.raw_memory_ptr(),
UsageInfo(mapping.mapped_size(), mapping.guid()));
}
void SharedMemoryTracker::DecrementMemoryUsage(
const SharedMemoryMapping& mapping) {
AutoLock hold(usages_lock_);
DCHECK(usages_.find(mapping.raw_memory_ptr()) != usages_.end());
usages_.erase(mapping.raw_memory_ptr());
}
SharedMemoryTracker::SharedMemoryTracker() {
#if BUILDFLAG(ENABLE_BASE_TRACING)
trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
this, "SharedMemoryTracker", nullptr);
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
}
SharedMemoryTracker::~SharedMemoryTracker() = default;
bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args,
trace_event::ProcessMemoryDump* pmd) {
AutoLock hold(usages_lock_);
for (const auto& usage : usages_) {
const trace_event::MemoryAllocatorDump* dump =
GetOrCreateSharedMemoryDumpInternal(
usage.first, usage.second.mapped_size, usage.second.mapped_id, pmd);
DCHECK(dump);
}
return true;
}
// static
const trace_event::MemoryAllocatorDump*
SharedMemoryTracker::GetOrCreateSharedMemoryDumpInternal(
void* mapped_memory,
size_t mapped_size,
const UnguessableToken& mapped_id,
trace_event::ProcessMemoryDump* pmd) {
#if BUILDFLAG(ENABLE_BASE_TRACING)
const std::string dump_name = GetDumpNameForTracing(mapped_id);
trace_event::MemoryAllocatorDump* local_dump =
pmd->GetAllocatorDump(dump_name);
if (local_dump)
return local_dump;
size_t virtual_size = mapped_size;
// If resident size is not available, a virtual size is used as fallback.
size_t size = virtual_size;
#if defined(COUNT_RESIDENT_BYTES_SUPPORTED)
absl::optional<size_t> resident_size =
trace_event::ProcessMemoryDump::CountResidentBytesInSharedMemory(
mapped_memory, mapped_size);
if (resident_size.has_value())
size = resident_size.value();
#endif
local_dump = pmd->CreateAllocatorDump(dump_name);
local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
trace_event::MemoryAllocatorDump::kUnitsBytes, size);
local_dump->AddScalar("virtual_size",
trace_event::MemoryAllocatorDump::kUnitsBytes,
virtual_size);
auto global_dump_guid = GetGlobalDumpIdForTracing(mapped_id);
trace_event::MemoryAllocatorDump* global_dump =
pmd->CreateSharedGlobalAllocatorDump(global_dump_guid);
global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize,
trace_event::MemoryAllocatorDump::kUnitsBytes, size);
// The edges will be overriden by the clients with correct importance.
pmd->AddOverridableOwnershipEdge(local_dump->guid(), global_dump->guid(),
0 /* importance */);
return local_dump;
#else // BUILDFLAG(ENABLE_BASE_TRACING)
NOTREACHED();
return nullptr;
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
}
} // namespace
|