1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright 2015 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/process_memory_dump.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <errno.h> 8cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <vector> 9cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 10cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "base/process/process_metrics.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/process_memory_totals.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/trace_event_argument.h" 13cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include "build/build_config.h" 14cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 15cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#if defined(OS_POSIX) 16cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#include <sys/mman.h> 17cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#endif 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace trace_event { 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace { 23cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratconst char kEdgeTypeOwnership[] = "ownership"; 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratstd::string GetSharedGlobalAllocatorDumpName( 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& guid) { 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return "global/" + guid.ToString(); 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 30cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 33cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#if defined(COUNT_RESIDENT_BYTES_SUPPORTED) 34cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko// static 35cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkosize_t ProcessMemoryDump::CountResidentBytes(void* start_address, 36cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko size_t mapped_size) { 37cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const size_t page_size = GetPageSize(); 38cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const uintptr_t start_pointer = reinterpret_cast<uintptr_t>(start_address); 39cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko DCHECK_EQ(0u, start_pointer % page_size); 40cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 41cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // This function allocates a char vector of size number of pages in the given 42cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // mapped_size. To avoid allocating a large array, the memory is split into 43cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // chunks. Maximum size of vector allocated, will be 44cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // kPageChunkSize / page_size. 45cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const size_t kMaxChunkSize = 32 * 1024 * 1024; 46cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko size_t offset = 0; 47cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko size_t total_resident_size = 0; 48cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko int result = 0; 49cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko while (offset < mapped_size) { 50cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko void* chunk_start = reinterpret_cast<void*>(start_pointer + offset); 51cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const size_t chunk_size = std::min(mapped_size - offset, kMaxChunkSize); 52cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const size_t page_count = (chunk_size + page_size - 1) / page_size; 53cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko size_t resident_page_count = 0; 54cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 55cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#if defined(OS_MACOSX) || defined(OS_IOS) 56cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<char> vec(page_count + 1); 57cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // mincore in MAC does not fail with EAGAIN. 58cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko result = mincore(chunk_start, chunk_size, vec.data()); 59cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (result) 60cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko break; 61cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 62cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (size_t i = 0; i < page_count; i++) 63cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko resident_page_count += vec[i] & MINCORE_INCORE ? 1 : 0; 64cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#else // defined(OS_MACOSX) || defined(OS_IOS) 65cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko std::vector<unsigned char> vec(page_count + 1); 66cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko int error_counter = 0; 67cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // HANDLE_EINTR tries for 100 times. So following the same pattern. 68cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko do { 69cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko result = mincore(chunk_start, chunk_size, vec.data()); 70cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } while (result == -1 && errno == EAGAIN && error_counter++ < 100); 71cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (result) 72cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko break; 73cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 74cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (size_t i = 0; i < page_count; i++) 75cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko resident_page_count += vec[i]; 76cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#endif // defined(OS_MACOSX) || defined(OS_IOS) 77cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 78cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko total_resident_size += resident_page_count * page_size; 79cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko offset += kMaxChunkSize; 80cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 81cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 82cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko DCHECK_EQ(0, result); 83cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (result) { 84cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko total_resident_size = 0; 85cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko LOG(ERROR) << "mincore() call failed. The resident size is invalid"; 86cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 87cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return total_resident_size; 88cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko} 89cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko#endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) 90cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessMemoryDump::ProcessMemoryDump( 92b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const scoped_refptr<MemoryDumpSessionState>& session_state) 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat : has_process_totals_(false), 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat has_process_mmaps_(false), 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat session_state_(session_state) { 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratProcessMemoryDump::~ProcessMemoryDump() { 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& absolute_name) { 103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump* mad = new MemoryAllocatorDump(absolute_name, this); 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddAllocatorDumpInternal(mad); // Takes ownership of |mad|. 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return mad; 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& absolute_name, 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& guid) { 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump* mad = new MemoryAllocatorDump(absolute_name, this, guid); 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddAllocatorDumpInternal(mad); // Takes ownership of |mad|. 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return mad; 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::AddAllocatorDumpInternal(MemoryAllocatorDump* mad) { 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ(0ul, allocator_dumps_.count(mad->absolute_name())); 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_storage_.push_back(mad); 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_[mad->absolute_name()] = mad; 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump( 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& absolute_name) const { 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat auto it = allocator_dumps_.find(absolute_name); 125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return it == allocator_dumps_.end() ? nullptr : it->second; 126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 128cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex VakulenkoMemoryAllocatorDump* ProcessMemoryDump::GetOrCreateAllocatorDump( 129cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko const std::string& absolute_name) { 130cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko MemoryAllocatorDump* mad = GetAllocatorDump(absolute_name); 131cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return mad ? mad : CreateAllocatorDump(absolute_name); 132cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko} 133cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMemoryAllocatorDump* ProcessMemoryDump::CreateSharedGlobalAllocatorDump( 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& guid) { 136cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // A shared allocator dump can be shared within a process and the guid could 137cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko // have been created already. 138cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko MemoryAllocatorDump* allocator_dump = GetSharedGlobalAllocatorDump(guid); 139cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko return allocator_dump ? allocator_dump 140cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko : CreateAllocatorDump( 141cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko GetSharedGlobalAllocatorDumpName(guid), guid); 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMemoryAllocatorDump* ProcessMemoryDump::GetSharedGlobalAllocatorDump( 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& guid) const { 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return GetAllocatorDump(GetSharedGlobalAllocatorDumpName(guid)); 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 149cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenkovoid ProcessMemoryDump::AddHeapDump(const std::string& absolute_name, 150cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko scoped_refptr<TracedValue> heap_dump) { 151cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko DCHECK_EQ(0ul, heap_dumps_.count(absolute_name)); 152cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko heap_dumps_[absolute_name] = heap_dump; 153cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko} 154cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::Clear() { 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (has_process_totals_) { 157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat process_totals_.Clear(); 158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat has_process_totals_ = false; 159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (has_process_mmaps_) { 162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat process_mmaps_.Clear(); 163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat has_process_mmaps_ = false; 164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_storage_.clear(); 167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_.clear(); 168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_edges_.clear(); 169cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko heap_dumps_.clear(); 170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::TakeAllDumpsFrom(ProcessMemoryDump* other) { 173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK(!other->has_process_totals() && !other->has_process_mmaps()); 174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Moves the ownership of all MemoryAllocatorDump(s) contained in |other| 176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // into this ProcessMemoryDump. 177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (MemoryAllocatorDump* mad : other->allocator_dumps_storage_) { 178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Check that we don't merge duplicates. 179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat DCHECK_EQ(0ul, allocator_dumps_.count(mad->absolute_name())); 180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_storage_.push_back(mad); 181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_[mad->absolute_name()] = mad; 182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other->allocator_dumps_storage_.weak_clear(); 184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other->allocator_dumps_.clear(); 185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // Move all the edges. 187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_edges_.insert(allocator_dumps_edges_.end(), 188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other->allocator_dumps_edges_.begin(), 189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other->allocator_dumps_edges_.end()); 190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat other->allocator_dumps_edges_.clear(); 191cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 192cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko heap_dumps_.insert(other->heap_dumps_.begin(), other->heap_dumps_.end()); 193cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko other->heap_dumps_.clear(); 194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::AsValueInto(TracedValue* value) const { 197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (has_process_totals_) { 198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->BeginDictionary("process_totals"); 199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat process_totals_.AsValueInto(value); 200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->EndDictionary(); 201b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (has_process_mmaps_) { 204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->BeginDictionary("process_mmaps"); 205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat process_mmaps_.AsValueInto(value); 206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->EndDictionary(); 207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (allocator_dumps_storage_.size() > 0) { 210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->BeginDictionary("allocators"); 211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const MemoryAllocatorDump* allocator_dump : allocator_dumps_storage_) 212b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dump->AsValueInto(value); 213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->EndDictionary(); 214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 216cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko if (heap_dumps_.size() > 0) { 217cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko value->BeginDictionary("heaps"); 218cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko for (const auto& name_and_dump : heap_dumps_) 219cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko value->SetValueWithCopiedName(name_and_dump.first, *name_and_dump.second); 220cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko value->EndDictionary(); // "heaps" 221cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko } 222cce46a0c214b37e8da48c522c83037e8ffa4f9fdAlex Vakulenko 223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->BeginArray("allocators_graph"); 224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const MemoryAllocatorDumpEdge& edge : allocator_dumps_edges_) { 225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->BeginDictionary(); 226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->SetString("source", edge.source.ToString()); 227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->SetString("target", edge.target.ToString()); 228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->SetInteger("importance", edge.importance); 229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->SetString("type", edge.type); 230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->EndDictionary(); 231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value->EndArray(); 233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, 236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& target, 237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat int importance) { 238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocator_dumps_edges_.push_back( 239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat {source, target, importance, kEdgeTypeOwnership}); 240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::AddOwnershipEdge( 243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& source, 244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const MemoryAllocatorDumpGuid& target) { 245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddOwnershipEdge(source, target, 0 /* importance */); 246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source, 249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const std::string& target_node_name) { 250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string child_mad_name = target_node_name + "/__" + source.ToString(); 251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump* target_child_mad = CreateAllocatorDump(child_mad_name); 252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddOwnershipEdge(source, target_child_mad->guid()); 253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace trace_event 256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 257