ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 1 | // Copyright 2015 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 | |
| 5 | #include "gin/v8_isolate_memory_dump_provider.h" |
| 6 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 7 | #include "base/strings/stringprintf.h" |
| 8 | #include "base/thread_task_runner_handle.h" |
| 9 | #include "base/trace_event/memory_dump_manager.h" |
| 10 | #include "base/trace_event/process_memory_dump.h" |
| 11 | #include "gin/public/isolate_holder.h" |
| 12 | #include "v8/include/v8.h" |
| 13 | |
| 14 | namespace gin { |
| 15 | |
| 16 | namespace { |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 17 | const char kHeapSpacesDumpName[] = "heap_spaces"; |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 18 | const char kHeapObjectsDumpName[] = "heap_objects"; |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 19 | const char kAvailableSizeAttribute[] = "available_size_in_bytes"; |
| 20 | } // namespace |
| 21 | |
| 22 | V8IsolateMemoryDumpProvider::V8IsolateMemoryDumpProvider( |
| 23 | IsolateHolder* isolate_holder) |
| 24 | : isolate_holder_(isolate_holder) { |
| 25 | base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 26 | this, base::ThreadTaskRunnerHandle::Get()); |
| 27 | } |
| 28 | |
| 29 | V8IsolateMemoryDumpProvider::~V8IsolateMemoryDumpProvider() { |
| 30 | base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
| 31 | this); |
| 32 | } |
| 33 | |
| 34 | // Called at trace dump point time. Creates a snapshot with the memory counters |
| 35 | // for the current isolate. |
| 36 | bool V8IsolateMemoryDumpProvider::OnMemoryDump( |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 37 | base::trace_event::ProcessMemoryDump* process_memory_dump) { |
| 38 | std::string dump_base_name = |
| 39 | base::StringPrintf("v8/isolate_%p", isolate_holder_->isolate()); |
| 40 | std::string space_dump_name = dump_base_name + "/" + kHeapSpacesDumpName; |
| 41 | std::string object_dump_name = dump_base_name + "/" + kHeapObjectsDumpName; |
| 42 | process_memory_dump->AddOwnershipEdge( |
| 43 | process_memory_dump->CreateAllocatorDump(object_dump_name)->guid(), |
| 44 | process_memory_dump->CreateAllocatorDump(space_dump_name)->guid()); |
| 45 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 46 | if (isolate_holder_->access_mode() == IsolateHolder::kUseLocker) { |
| 47 | v8::Locker locked(isolate_holder_->isolate()); |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 48 | DumpHeapSpacesStatistics(process_memory_dump, space_dump_name); |
| 49 | DumpHeapObjectStatistics(process_memory_dump, object_dump_name); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 50 | } else { |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 51 | DumpHeapSpacesStatistics(process_memory_dump, space_dump_name); |
| 52 | DumpHeapObjectStatistics(process_memory_dump, object_dump_name); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 53 | } |
| 54 | return true; |
| 55 | } |
| 56 | |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 57 | void V8IsolateMemoryDumpProvider::DumpHeapSpacesStatistics( |
| 58 | base::trace_event::ProcessMemoryDump* process_memory_dump, |
| 59 | const std::string& dump_base_name) { |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 60 | v8::HeapStatistics heap_statistics; |
| 61 | isolate_holder_->isolate()->GetHeapStatistics(&heap_statistics); |
| 62 | |
| 63 | size_t known_spaces_used_size = 0; |
| 64 | size_t known_spaces_size = 0; |
ssid | 49aa14c7 | 2015-05-29 13:03:59 | [diff] [blame] | 65 | size_t known_spaces_available_size = 0; |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 66 | size_t number_of_spaces = isolate_holder_->isolate()->NumberOfHeapSpaces(); |
| 67 | for (size_t space = 0; space < number_of_spaces; space++) { |
| 68 | v8::HeapSpaceStatistics space_statistics; |
| 69 | isolate_holder_->isolate()->GetHeapSpaceStatistics(&space_statistics, |
| 70 | space); |
| 71 | const size_t space_size = space_statistics.space_size(); |
| 72 | const size_t space_used_size = space_statistics.space_used_size(); |
ssid | 49aa14c7 | 2015-05-29 13:03:59 | [diff] [blame] | 73 | const size_t space_available_size = space_statistics.space_available_size(); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 74 | |
| 75 | known_spaces_size += space_size; |
| 76 | known_spaces_used_size += space_used_size; |
ssid | 49aa14c7 | 2015-05-29 13:03:59 | [diff] [blame] | 77 | known_spaces_available_size += space_available_size; |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 78 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 79 | base::trace_event::MemoryAllocatorDump* space_dump = |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 80 | process_memory_dump->CreateAllocatorDump(dump_base_name + "/" + |
| 81 | space_statistics.space_name()); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 82 | space_dump->AddScalar( |
| 83 | base::trace_event::MemoryAllocatorDump::kNameOuterSize, |
| 84 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, space_size); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 85 | space_dump->AddScalar( |
| 86 | base::trace_event::MemoryAllocatorDump::kNameInnerSize, |
| 87 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, space_used_size); |
| 88 | space_dump->AddScalar(kAvailableSizeAttribute, |
| 89 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
ssid | 49aa14c7 | 2015-05-29 13:03:59 | [diff] [blame] | 90 | space_available_size); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 91 | } |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 92 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 93 | // Compute the rest of the memory, not accounted by the spaces above. |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 94 | base::trace_event::MemoryAllocatorDump* other_spaces_dump = |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 95 | process_memory_dump->CreateAllocatorDump(dump_base_name + |
| 96 | "/other_spaces"); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 97 | other_spaces_dump->AddScalar( |
| 98 | base::trace_event::MemoryAllocatorDump::kNameOuterSize, |
| 99 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 100 | heap_statistics.total_heap_size() - known_spaces_size); |
| 101 | other_spaces_dump->AddScalar( |
| 102 | base::trace_event::MemoryAllocatorDump::kNameInnerSize, |
| 103 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 104 | heap_statistics.used_heap_size() - known_spaces_used_size); |
| 105 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 106 | other_spaces_dump->AddScalar( |
| 107 | kAvailableSizeAttribute, |
ssid | 49aa14c7 | 2015-05-29 13:03:59 | [diff] [blame] | 108 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 109 | heap_statistics.total_available_size() - known_spaces_available_size); |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 110 | } |
| 111 | |
ssid | f51216b0 | 2015-06-04 19:46:23 | [diff] [blame^] | 112 | void V8IsolateMemoryDumpProvider::DumpHeapObjectStatistics( |
| 113 | base::trace_event::ProcessMemoryDump* process_memory_dump, |
| 114 | const std::string& dump_base_name) { |
| 115 | const size_t object_types = |
| 116 | isolate_holder_->isolate()->NumberOfTrackedHeapObjectTypes(); |
| 117 | for (size_t type_index = 0; type_index < object_types; type_index++) { |
| 118 | v8::HeapObjectStatistics object_statistics; |
| 119 | if (!isolate_holder_->isolate()->GetHeapObjectStatisticsAtLastGC( |
| 120 | &object_statistics, type_index)) |
| 121 | continue; |
| 122 | |
| 123 | std::string dump_name = |
| 124 | dump_base_name + "/" + object_statistics.object_type(); |
| 125 | if (object_statistics.object_sub_type()[0] != '\0') |
| 126 | dump_name += std::string("/") + object_statistics.object_sub_type(); |
| 127 | base::trace_event::MemoryAllocatorDump* object_dump = |
| 128 | process_memory_dump->CreateAllocatorDump(dump_name); |
| 129 | |
| 130 | object_dump->AddScalar( |
| 131 | base::trace_event::MemoryAllocatorDump::kNameObjectsCount, |
| 132 | base::trace_event::MemoryAllocatorDump::kUnitsObjects, |
| 133 | object_statistics.object_count()); |
| 134 | object_dump->AddScalar( |
| 135 | base::trace_event::MemoryAllocatorDump::kNameInnerSize, |
| 136 | base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 137 | object_statistics.object_size()); |
| 138 | } |
| 139 | |
| 140 | process_memory_dump->AddOwnershipEdge( |
| 141 | process_memory_dump->CreateAllocatorDump(dump_base_name + |
| 142 | "/CODE_TYPE/CODE_KIND")->guid(), |
| 143 | process_memory_dump->CreateAllocatorDump(dump_base_name + |
| 144 | "/CODE_TYPE/CODE_AGE")->guid()); |
| 145 | } |
| 146 | |
ssid | 83aa5be | 2015-05-08 12:03:26 | [diff] [blame] | 147 | } // namespace gin |