Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(613)

Side by Side Diff: runtime/vm/heap_profiler.h

Issue 10452006: Implement a heap profiler for the Dart managed heap. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address final review comments Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/heap.cc ('k') | runtime/vm/heap_profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 #ifndef VM_HEAP_PROFILER_H_
6 #define VM_HEAP_PROFILER_H_
7
8 #include <set>
9
10 #include "include/dart_api.h"
11 #include "vm/globals.h"
12 #include "vm/handles.h"
13 #include "vm/object.h"
14 #include "vm/visitor.h"
15
16 namespace dart {
17
18 // A HeapProfiler writes a snapshot of the heap for off-line analysis.
19 // The heap is written in binary HPROF format, which is a sequence of
20 // self describing records. A description of the HPROF format can be
21 // found at
22 //
23 // http://java.net/downloads/heap-snapshot/hprof-binary-format.html
24 //
25 // HPROF was not designed for Dart, but most Dart concepts can be
26 // mapped directly into HPROF. Some features, such as immediate
27 // objects and variable length objects, require a translation.
28 class HeapProfiler {
29 public:
30 enum Tag {
31 kStringInUtf8 = 0x01,
32 kLoadClass = 0x02,
33 kUnloadClass = 0x03,
34 kStackFrame = 0x04,
35 kStackTrace = 0x05,
36 kAllocSites = 0x06,
37 kHeapSummary = 0x07,
38 kStartThread = 0x0A,
39 kEndThread = 0x0B,
40 kHeapDump = 0x0C,
41 kCpuSamples = 0x0D,
42 kControlSettings = 0x0E,
43 kHeapDumpSummary = 0x1C,
44 kHeapDumpEnd = 0x2C
45 };
46
47 // Sub-record tags describe sub-records within a heap dump.
48 enum Subtag {
49 kRootJniGlobal = 0x01,
50 kRootJniLocal = 0x01,
51 kRootJavaFrame = 0x03,
52 kRootNativeStack = 0x04,
53 kRootStickyClass = 0x05,
54 kRootThreadBlock = 0x06,
55 kRootMonitorUsed = 0x07,
56 kRootThreadObject = 0x08,
57 kClassDump = 0x20,
58 kInstanceDump = 0x21,
59 kObjectArrayDump = 0x22,
60 kPrimitiveArrayDump = 0x23,
61 kRootUnknown = 0xFF
62 };
63
64 // Tags for describing element and field types.
65 enum BasicType {
66 kObject = 2,
67 kBoolean = 4,
68 kChar = 5,
69 kFloat = 6,
70 kDouble = 7,
71 kByte = 8,
72 kShort = 9,
73 kInt = 10,
74 kLong = 11
75 };
76
77 HeapProfiler(Dart_HeapProfileWriteCallback callback, void* stream);
78 ~HeapProfiler();
79
80 // Writes a root to the heap dump.
81 void WriteRoot(const RawObject* raw_obj);
82
83 // Writes a object to the heap dump.
84 void WriteObject(const RawObject* raw_obj);
85
86 private:
87 // Record tags describe top-level records.
88 // A growable array of bytes used to build a record body.
89 class Buffer {
90 public:
91 Buffer() : data_(0), size_(0), capacity_(0) {
92 }
93 ~Buffer();
94
95 // Writes an array of bytes to the buffer, increasing the capacity
96 // as needed.
97 void Write(const uint8_t* data, intptr_t length);
98
99 // Returns the underlying element storage.
100 const uint8_t* Data() const {
101 return data_;
102 }
103
104 // Returns the number of elements written to the buffer.
105 intptr_t Size() const {
106 return size_;
107 }
108
109 private:
110 // Resizes the element storage, if needed.
111 void EnsureCapacity(intptr_t size);
112
113 uint8_t* data_;
114
115 intptr_t size_;
116
117 // Size of the element storage.
118 intptr_t capacity_;
119
120 DISALLOW_COPY_AND_ASSIGN(Buffer);
121 };
122
123 // A top-level data record.
124 class Record {
125 public:
126 Record(uint8_t tag, HeapProfiler* profiler)
127 : tag_(tag), profiler_(profiler) {
128 }
129 ~Record() {
130 profiler_->WriteRecord(*this);
131 }
132
133 // Returns the tag describing the record format.
134 uint8_t Tag() const {
135 return tag_;
136 }
137
138 // Returns a millisecond time delta, always 0.
139 uint8_t Time() const {
140 return 0;
141 }
142
143 // Returns the record length in bytes.
144 uint32_t Length() const {
145 return body_.Size();
146 }
147
148 // Returns the record body.
149 const uint8_t* Body() const {
150 return body_.Data();
151 }
152
153 // Appends an array of 8-bit values to the record body.
154 void Write(const uint8_t* value, intptr_t size);
155
156 // Appends an 8-, 16-, 32- or 64-bit value to the body in
157 // big-endian format.
158 void Write8(uint8_t value);
159 void Write16(uint16_t value);
160 void Write32(uint32_t value);
161 void Write64(uint64_t value);
162
163 // Appends an ID to the body.
164 void WritePointer(const void* value);
165
166 private:
167 // A tag value that describes the record format.
168 uint8_t tag_;
169
170 // The payload of the record as described by the tag.
171 Buffer body_;
172
173 // Parent object.
174 HeapProfiler* profiler_;
175
176 DISALLOW_COPY_AND_ASSIGN(Record);
177 };
178
179 // A sub-record within a heap dump record. Write calls are
180 // forwarded to the profilers heap dump record instance.
181 class SubRecord {
182 public:
183 // Starts a new sub-record within the heap dump record.
184 SubRecord(uint8_t sub_tag, HeapProfiler* profiler);
185 ~SubRecord();
186
187 // Appends an array of 8-bit values to the heap dump record.
188 void Write(const uint8_t* value, intptr_t size);
189
190 // Appends an 8-, 16-, 32- or 64-bit value to the heap dump
191 // record.
192 void Write8(uint8_t value);
193 void Write16(uint16_t value);
194 void Write32(uint32_t value);
195 void Write64(uint64_t value);
196
197 // Appends an ID to the current heap dump record.
198 void WritePointer(const void* value);
199
200 private:
201 // The record instance that receives forwarded write calls.
202 Record* record_;
203 };
204
205 // Id canonizers.
206 const RawClass* ClassId(const RawClass* raw_class);
207 const RawObject* ObjectId(const RawObject* raw_obj);
208 const char* StringId(const char* c_string);
209 const RawString* StringId(const RawString* raw_string);
210
211 // Invokes the write callback.
212 void Write(const void* data, intptr_t size);
213
214 // Writes the binary hprof header to the output stream.
215 void WriteHeader();
216
217 // Writes a record to the output stream.
218 void WriteRecord(const Record& record);
219
220
221 // Writes a string in utf-8 record to the output stream.
222 void WriteStringInUtf8(const char* c_string);
223 void WriteStringInUtf8(const RawString* raw_string);
224
225
226 // Writes a load class record to the output stream.
227 void WriteLoadClass(const RawClass* raw_class);
228
229 // Writes an empty stack trace to the output stream.
230 void WriteStackTrace();
231
232 // Writes a heap summary record to the output stream.
233 void WriteHeapSummary(uint32_t total_live_bytes,
234 uint32_t total_live_instances,
235 uint64_t total_bytes_allocated,
236 uint64_t total_instances_allocated);
237
238 // Writes a heap dump record to the output stream.
239 void WriteHeapDump();
240
241 // Writes a sub-record to the heap dump record.
242 void WriteClassDump(const RawClass* raw_class);
243 void WriteInstanceDump(const RawObject* raw_obj);
244 void WriteObjectArrayDump(const RawArray* raw_array);
245 void WritePrimitiveArrayDump(const RawByteArray* raw_byte_array,
246 uint8_t tag,
247 const void* data);
248
249 static const RawClass* GetClass(const RawObject* raw_obj);
250 static const RawClass* GetSuperClass(const RawClass* raw_class);
251
252 Dart_HeapProfileWriteCallback write_callback_;
253
254 void* output_stream_;
255
256 Record* heap_dump_record_;
257
258 std::set<const RawSmi*> smi_table_;
259 std::set<const RawClass*> class_table_;
260 std::set<const RawString*> string_table_;
261
262 DISALLOW_COPY_AND_ASSIGN(HeapProfiler);
263 };
264
265
266 // Writes a root sub-record to the heap dump for every strong handle.
267 class HeapProfilerRootVisitor : public ObjectPointerVisitor {
268 public:
269 explicit HeapProfilerRootVisitor(HeapProfiler* profiler)
270 : ObjectPointerVisitor(Isolate::Current()),
271 profiler_(profiler) {
272 }
273
274 virtual void VisitPointers(RawObject** first, RawObject** last);
275
276 private:
277 HeapProfiler* profiler_;
278 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapProfilerRootVisitor);
279 };
280
281
282 // Writes a root sub-record to the heap dump for every weak handle.
283 class HeapProfilerWeakRootVisitor : public HandleVisitor {
284 public:
285 explicit HeapProfilerWeakRootVisitor(HeapProfilerRootVisitor* visitor)
286 : visitor_(visitor) {
287 }
288
289 virtual void VisitHandle(uword addr);
290
291 private:
292 HeapProfilerRootVisitor* visitor_;
293 DISALLOW_COPY_AND_ASSIGN(HeapProfilerWeakRootVisitor);
294 };
295
296
297 // Writes a sub-record to the heap dump for every object in the heap.
298 class HeapProfilerObjectVisitor : public ObjectVisitor {
299 public:
300 explicit HeapProfilerObjectVisitor(HeapProfiler* profiler)
301 : profiler_(profiler) {
302 }
303
304 virtual void VisitObject(RawObject* obj);
305
306 private:
307 HeapProfiler* profiler_;
308 DISALLOW_COPY_AND_ASSIGN(HeapProfilerObjectVisitor);
309 };
310
311 } // namespace dart
312
313 #endif // VM_HEAP_PROFILER_H_
OLDNEW
« no previous file with comments | « runtime/vm/heap.cc ('k') | runtime/vm/heap_profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698