| OLD | NEW | 
|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "base/memory/shared_memory_tracker.h" | 5 #include "base/memory/shared_memory_tracker.h" | 
| 6 | 6 | 
| 7 #include "base/memory/shared_memory.h" | 7 #include "base/format_macros.h" | 
| 8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" | 
| 9 #include "base/trace_event/memory_dump_manager.h" | 9 #include "base/trace_event/memory_dump_manager.h" | 
| 10 #include "base/trace_event/process_memory_dump.h" | 10 #include "base/trace_event/process_memory_dump.h" | 
| 11 | 11 | 
| 12 namespace base { | 12 namespace base { | 
| 13 | 13 | 
| 14 SharedMemoryTracker::Usage::Usage() = default; |  | 
| 15 |  | 
| 16 SharedMemoryTracker::Usage::Usage(const Usage& rhs) = default; |  | 
| 17 |  | 
| 18 SharedMemoryTracker::Usage::~Usage() = default; |  | 
| 19 |  | 
| 20 // static | 14 // static | 
| 21 SharedMemoryTracker* SharedMemoryTracker::GetInstance() { | 15 SharedMemoryTracker* SharedMemoryTracker::GetInstance() { | 
| 22   static SharedMemoryTracker* instance = new SharedMemoryTracker; | 16   static SharedMemoryTracker* instance = new SharedMemoryTracker; | 
| 23   return instance; | 17   return instance; | 
| 24 } | 18 } | 
| 25 | 19 | 
|  | 20 // static | 
|  | 21 bool SharedMemoryTracker::AddOwnershipEdges( | 
|  | 22     trace_event::ProcessMemoryDump* pmd, | 
|  | 23     const trace_event::MemoryAllocatorDumpGuid& source, | 
|  | 24     const SharedMemory& shared_memory) { | 
|  | 25   std::string id_str = shared_memory.handle().GetGUIDNameForTracing(); | 
|  | 26   // The same dump name might be already created on single-process mode. | 
|  | 27   trace_event::MemoryAllocatorDump* dump = | 
|  | 28       pmd->GetOrCreateAllocatorDump(id_str); | 
|  | 29   pmd->AddOwnershipEdge(source, dump->guid()); | 
|  | 30   return true; | 
|  | 31 } | 
|  | 32 | 
| 26 void SharedMemoryTracker::IncrementMemoryUsage( | 33 void SharedMemoryTracker::IncrementMemoryUsage( | 
| 27     const SharedMemory& shared_memory) { | 34     const SharedMemory& shared_memory) { | 
| 28   Usage usage; |  | 
| 29   // |shared_memory|'s unique ID must be generated here and it'd be too late at |  | 
| 30   // OnMemoryDump. An ID is generated with a SharedMemoryHandle, but the handle |  | 
| 31   // might already be closed at that time. Now IncrementMemoryUsage is called |  | 
| 32   // just after mmap and the handle must live then. See the discussion at |  | 
| 33   // crbug.com/604726#c30. |  | 
| 34   SharedMemory::UniqueId id; |  | 
| 35   if (!shared_memory.GetUniqueId(&id)) |  | 
| 36     return; |  | 
| 37   usage.unique_id = id; |  | 
| 38   usage.size = shared_memory.mapped_size(); |  | 
| 39   AutoLock hold(usages_lock_); | 35   AutoLock hold(usages_lock_); | 
| 40   usages_[&shared_memory] = usage; | 36   usages_[&shared_memory] = shared_memory.mapped_size(); | 
| 41 } | 37 } | 
| 42 | 38 | 
| 43 void SharedMemoryTracker::DecrementMemoryUsage( | 39 void SharedMemoryTracker::DecrementMemoryUsage( | 
| 44     const SharedMemory& shared_memory) { | 40     const SharedMemory& shared_memory) { | 
| 45   AutoLock hold(usages_lock_); | 41   AutoLock hold(usages_lock_); | 
| 46   usages_.erase(&shared_memory); | 42   usages_.erase(&shared_memory); | 
| 47 } | 43 } | 
| 48 | 44 | 
| 49 bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args, | 45 bool SharedMemoryTracker::OnMemoryDump(const trace_event::MemoryDumpArgs& args, | 
| 50                                        trace_event::ProcessMemoryDump* pmd) { | 46                                        trace_event::ProcessMemoryDump* pmd) { | 
| 51   std::unordered_map<SharedMemory::UniqueId, size_t, SharedMemory::UniqueIdHash> | 47   for (auto& usage : usages_) { | 
| 52       sizes; | 48     const SharedMemory* shared_memory = usage.first; | 
| 53   { | 49     std::string dump_name = shared_memory->handle().GetGUIDNameForTracing(); | 
| 54     AutoLock hold(usages_lock_); | 50     if (dump_name.empty()) | 
| 55     for (const auto& usage : usages_) | 51       continue; | 
| 56       sizes[usage.second.unique_id] += usage.second.size; |  | 
| 57   } |  | 
| 58   for (auto& size : sizes) { |  | 
| 59     const SharedMemory::UniqueId& id = size.first; |  | 
| 60     std::string dump_name = StringPrintf("%s/%lld.%lld", "shared_memory", |  | 
| 61                                          static_cast<long long>(id.first), |  | 
| 62                                          static_cast<long long>(id.second)); |  | 
| 63     auto guid = trace_event::MemoryAllocatorDumpGuid(dump_name); |  | 
| 64     trace_event::MemoryAllocatorDump* local_dump = | 52     trace_event::MemoryAllocatorDump* local_dump = | 
| 65         pmd->CreateAllocatorDump(dump_name); | 53         pmd->GetOrCreateAllocatorDump(dump_name); | 
| 66     // TODO(hajimehoshi): The size is not resident size but virtual size so far. | 54     // TODO(hajimehoshi): The size is not resident size but virtual size so far. | 
| 67     // Fix this to record resident size. | 55     // Fix this to record resident size. | 
| 68     local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, | 56     local_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, | 
| 69                           trace_event::MemoryAllocatorDump::kUnitsBytes, | 57                           trace_event::MemoryAllocatorDump::kUnitsBytes, | 
| 70                           size.second); | 58                           usage.second); | 
|  | 59     auto guid = trace_event::MemoryAllocatorDumpGuid(dump_name); | 
| 71     trace_event::MemoryAllocatorDump* global_dump = | 60     trace_event::MemoryAllocatorDump* global_dump = | 
| 72         pmd->CreateSharedGlobalAllocatorDump(guid); | 61         pmd->CreateSharedGlobalAllocatorDump(guid); | 
| 73     global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, | 62     global_dump->AddScalar(trace_event::MemoryAllocatorDump::kNameSize, | 
| 74                            trace_event::MemoryAllocatorDump::kUnitsBytes, | 63                            trace_event::MemoryAllocatorDump::kUnitsBytes, | 
| 75                            size.second); | 64                            usage.second); | 
| 76     // TOOD(hajimehoshi): Detect which the shared memory comes from browser, | 65     // TOOD(hajimehoshi): Detect which the shared memory comes from browser, | 
| 77     // renderer or GPU process. | 66     // renderer or GPU process. | 
| 78     // TODO(hajimehoshi): Shared memory reported by GPU and discardable is | 67     // TODO(hajimehoshi): Shared memory reported by GPU and discardable is | 
| 79     // currently double-counted. Add ownership edges to avoid this. | 68     // currently double-counted. Add ownership edges to avoid this. | 
| 80     pmd->AddOwnershipEdge(local_dump->guid(), global_dump->guid()); | 69     pmd->AddOwnershipEdge(local_dump->guid(), global_dump->guid(), | 
|  | 70                           shared_memory->importance()); | 
| 81   } | 71   } | 
| 82   return true; | 72   return true; | 
| 83 } | 73 } | 
| 84 | 74 | 
| 85 SharedMemoryTracker::SharedMemoryTracker() { | 75 SharedMemoryTracker::SharedMemoryTracker() { | 
| 86   trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 76   trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 
| 87       this, "SharedMemoryTracker", nullptr); | 77       this, "SharedMemoryTracker", nullptr); | 
| 88 } | 78 } | 
| 89 | 79 | 
| 90 SharedMemoryTracker::~SharedMemoryTracker() = default; | 80 SharedMemoryTracker::~SharedMemoryTracker() = default; | 
| 91 | 81 | 
| 92 }  // namespace | 82 }  // namespace | 
| OLD | NEW | 
|---|