shared_memory_tracker.cc 4.8 KB

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