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.
5 #include "gin/v8_isolate_memory_dump_provider.h"
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"
17 const char kHeapSpacesDumpName
[] = "heap_spaces";
18 const char kHeapObjectsDumpName
[] = "heap_objects";
19 const char kAvailableSizeAttribute
[] = "available_size_in_bytes";
22 V8IsolateMemoryDumpProvider::V8IsolateMemoryDumpProvider(
23 IsolateHolder
* isolate_holder
)
24 : isolate_holder_(isolate_holder
) {
25 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
26 this, base::ThreadTaskRunnerHandle::Get());
29 V8IsolateMemoryDumpProvider::~V8IsolateMemoryDumpProvider() {
30 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
34 // Called at trace dump point time. Creates a snapshot with the memory counters
35 // for the current isolate.
36 bool V8IsolateMemoryDumpProvider::OnMemoryDump(
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());
46 if (isolate_holder_
->access_mode() == IsolateHolder::kUseLocker
) {
47 v8::Locker
locked(isolate_holder_
->isolate());
48 DumpHeapSpacesStatistics(process_memory_dump
, space_dump_name
);
49 DumpHeapObjectStatistics(process_memory_dump
, object_dump_name
);
51 DumpHeapSpacesStatistics(process_memory_dump
, space_dump_name
);
52 DumpHeapObjectStatistics(process_memory_dump
, object_dump_name
);
57 void V8IsolateMemoryDumpProvider::DumpHeapSpacesStatistics(
58 base::trace_event::ProcessMemoryDump
* process_memory_dump
,
59 const std::string
& dump_base_name
) {
60 v8::HeapStatistics heap_statistics
;
61 isolate_holder_
->isolate()->GetHeapStatistics(&heap_statistics
);
63 size_t known_spaces_used_size
= 0;
64 size_t known_spaces_size
= 0;
65 size_t known_spaces_available_size
= 0;
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
,
71 const size_t space_size
= space_statistics
.space_size();
72 const size_t space_used_size
= space_statistics
.space_used_size();
73 const size_t space_available_size
= space_statistics
.space_available_size();
75 known_spaces_size
+= space_size
;
76 known_spaces_used_size
+= space_used_size
;
77 known_spaces_available_size
+= space_available_size
;
79 base::trace_event::MemoryAllocatorDump
* space_dump
=
80 process_memory_dump
->CreateAllocatorDump(dump_base_name
+ "/" +
81 space_statistics
.space_name());
82 space_dump
->AddScalar(
83 base::trace_event::MemoryAllocatorDump::kNameOuterSize
,
84 base::trace_event::MemoryAllocatorDump::kUnitsBytes
, space_size
);
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
,
90 space_available_size
);
93 // Compute the rest of the memory, not accounted by the spaces above.
94 base::trace_event::MemoryAllocatorDump
* other_spaces_dump
=
95 process_memory_dump
->CreateAllocatorDump(dump_base_name
+
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
);
106 other_spaces_dump
->AddScalar(
107 kAvailableSizeAttribute
,
108 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
109 heap_statistics
.total_available_size() - known_spaces_available_size
);
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
))
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
);
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());
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());