1 // Copyright 2010 the V8 project 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 #ifndef V8_V8_PROFILER_H_ 6 #define V8_V8_PROFILER_H_ 7 8 #include "v8.h" 9 10 /** 11 * Profiler support for the V8 JavaScript engine. 12 */ 13 namespace v8 { 14 15 class HeapGraphNode; 16 struct HeapStatsUpdate; 17 18 typedef uint32_t SnapshotObjectId; 19 20 /** 21 * CpuProfileNode represents a node in a call graph. 22 */ 23 class V8_EXPORT CpuProfileNode { 24 public: 25 /** Returns function name (empty string for anonymous functions.) */ 26 Handle<String> GetFunctionName() const; 27 28 /** Returns id of the script where function is located. */ 29 int GetScriptId() const; 30 31 /** Returns resource name for script from where the function originates. */ 32 Handle<String> GetScriptResourceName() const; 33 34 /** 35 * Returns the number, 1-based, of the line where the function originates. 36 * kNoLineNumberInfo if no line number information is available. 37 */ 38 int GetLineNumber() const; 39 40 /** 41 * Returns 1-based number of the column where the function originates. 42 * kNoColumnNumberInfo if no column number information is available. 43 */ 44 int GetColumnNumber() const; 45 46 /** Returns bailout reason for the function 47 * if the optimization was disabled for it. 48 */ 49 const char* GetBailoutReason() const; 50 51 /** 52 * Returns the count of samples where the function was currently executing. 53 */ 54 unsigned GetHitCount() const; 55 56 /** Returns function entry UID. */ 57 unsigned GetCallUid() const; 58 59 /** Returns id of the node. The id is unique within the tree */ 60 unsigned GetNodeId() const; 61 62 /** Returns child nodes count of the node. */ 63 int GetChildrenCount() const; 64 65 /** Retrieves a child node by index. */ 66 const CpuProfileNode* GetChild(int index) const; 67 68 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; 69 static const int kNoColumnNumberInfo = Message::kNoColumnInfo; 70 }; 71 72 73 /** 74 * CpuProfile contains a CPU profile in a form of top-down call tree 75 * (from main() down to functions that do all the work). 76 */ 77 class V8_EXPORT CpuProfile { 78 public: 79 /** Returns CPU profile title. */ 80 Handle<String> GetTitle() const; 81 82 /** Returns the root node of the top down call tree. */ 83 const CpuProfileNode* GetTopDownRoot() const; 84 85 /** 86 * Returns number of samples recorded. The samples are not recorded unless 87 * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true. 88 */ 89 int GetSamplesCount() const; 90 91 /** 92 * Returns profile node corresponding to the top frame the sample at 93 * the given index. 94 */ 95 const CpuProfileNode* GetSample(int index) const; 96 97 /** 98 * Returns the timestamp of the sample. The timestamp is the number of 99 * microseconds since some unspecified starting point. 100 * The point is equal to the starting point used by GetStartTime. 101 */ 102 int64_t GetSampleTimestamp(int index) const; 103 104 /** 105 * Returns time when the profile recording was started (in microseconds) 106 * since some unspecified starting point. 107 */ 108 int64_t GetStartTime() const; 109 110 /** 111 * Returns time when the profile recording was stopped (in microseconds) 112 * since some unspecified starting point. 113 * The point is equal to the starting point used by GetStartTime. 114 */ 115 int64_t GetEndTime() const; 116 117 /** 118 * Deletes the profile and removes it from CpuProfiler's list. 119 * All pointers to nodes previously returned become invalid. 120 */ 121 void Delete(); 122 }; 123 124 125 /** 126 * Interface for controlling CPU profiling. Instance of the 127 * profiler can be retrieved using v8::Isolate::GetCpuProfiler. 128 */ 129 class V8_EXPORT CpuProfiler { 130 public: 131 /** 132 * Changes default CPU profiler sampling interval to the specified number 133 * of microseconds. Default interval is 1000us. This method must be called 134 * when there are no profiles being recorded. 135 */ 136 void SetSamplingInterval(int us); 137 138 /** 139 * Starts collecting CPU profile. Title may be an empty string. It 140 * is allowed to have several profiles being collected at 141 * once. Attempts to start collecting several profiles with the same 142 * title are silently ignored. While collecting a profile, functions 143 * from all security contexts are included in it. The token-based 144 * filtering is only performed when querying for a profile. 145 * 146 * |record_samples| parameter controls whether individual samples should 147 * be recorded in addition to the aggregated tree. 148 */ 149 void StartProfiling(Handle<String> title, bool record_samples = false); 150 151 /** Deprecated. Use StartProfiling instead. */ 152 V8_DEPRECATED("Use StartProfiling", 153 void StartCpuProfiling(Handle<String> title, 154 bool record_samples = false)); 155 156 /** 157 * Stops collecting CPU profile with a given title and returns it. 158 * If the title given is empty, finishes the last profile started. 159 */ 160 CpuProfile* StopProfiling(Handle<String> title); 161 162 /** Deprecated. Use StopProfiling instead. */ 163 V8_DEPRECATED("Use StopProfiling", 164 const CpuProfile* StopCpuProfiling(Handle<String> title)); 165 166 /** 167 * Tells the profiler whether the embedder is idle. 168 */ 169 void SetIdle(bool is_idle); 170 171 private: 172 CpuProfiler(); 173 ~CpuProfiler(); 174 CpuProfiler(const CpuProfiler&); 175 CpuProfiler& operator=(const CpuProfiler&); 176 }; 177 178 179 /** 180 * HeapSnapshotEdge represents a directed connection between heap 181 * graph nodes: from retainers to retained nodes. 182 */ 183 class V8_EXPORT HeapGraphEdge { 184 public: 185 enum Type { 186 kContextVariable = 0, // A variable from a function context. 187 kElement = 1, // An element of an array. 188 kProperty = 2, // A named object property. 189 kInternal = 3, // A link that can't be accessed from JS, 190 // thus, its name isn't a real property name 191 // (e.g. parts of a ConsString). 192 kHidden = 4, // A link that is needed for proper sizes 193 // calculation, but may be hidden from user. 194 kShortcut = 5, // A link that must not be followed during 195 // sizes calculation. 196 kWeak = 6 // A weak reference (ignored by the GC). 197 }; 198 199 /** Returns edge type (see HeapGraphEdge::Type). */ 200 Type GetType() const; 201 202 /** 203 * Returns edge name. This can be a variable name, an element index, or 204 * a property name. 205 */ 206 Handle<Value> GetName() const; 207 208 /** Returns origin node. */ 209 const HeapGraphNode* GetFromNode() const; 210 211 /** Returns destination node. */ 212 const HeapGraphNode* GetToNode() const; 213 }; 214 215 216 /** 217 * HeapGraphNode represents a node in a heap graph. 218 */ 219 class V8_EXPORT HeapGraphNode { 220 public: 221 enum Type { 222 kHidden = 0, // Hidden node, may be filtered when shown to user. 223 kArray = 1, // An array of elements. 224 kString = 2, // A string. 225 kObject = 3, // A JS object (except for arrays and strings). 226 kCode = 4, // Compiled code. 227 kClosure = 5, // Function closure. 228 kRegExp = 6, // RegExp. 229 kHeapNumber = 7, // Number stored in the heap. 230 kNative = 8, // Native object (not from V8 heap). 231 kSynthetic = 9, // Synthetic object, usualy used for grouping 232 // snapshot items together. 233 kConsString = 10, // Concatenated string. A pair of pointers to strings. 234 kSlicedString = 11, // Sliced string. A fragment of another string. 235 kSymbol = 12 // A Symbol (ES6). 236 }; 237 238 /** Returns node type (see HeapGraphNode::Type). */ 239 Type GetType() const; 240 241 /** 242 * Returns node name. Depending on node's type this can be the name 243 * of the constructor (for objects), the name of the function (for 244 * closures), string value, or an empty string (for compiled code). 245 */ 246 Handle<String> GetName() const; 247 248 /** 249 * Returns node id. For the same heap object, the id remains the same 250 * across all snapshots. 251 */ 252 SnapshotObjectId GetId() const; 253 254 /** Returns node's own size, in bytes. */ 255 V8_DEPRECATED("Use GetShallowSize instead", 256 int GetSelfSize() const); 257 258 /** Returns node's own size, in bytes. */ 259 size_t GetShallowSize() const; 260 261 /** Returns child nodes count of the node. */ 262 int GetChildrenCount() const; 263 264 /** Retrieves a child by index. */ 265 const HeapGraphEdge* GetChild(int index) const; 266 }; 267 268 269 /** 270 * An interface for exporting data from V8, using "push" model. 271 */ 272 class V8_EXPORT OutputStream { // NOLINT 273 public: 274 enum WriteResult { 275 kContinue = 0, 276 kAbort = 1 277 }; ~OutputStream()278 virtual ~OutputStream() {} 279 /** Notify about the end of stream. */ 280 virtual void EndOfStream() = 0; 281 /** Get preferred output chunk size. Called only once. */ GetChunkSize()282 virtual int GetChunkSize() { return 1024; } 283 /** 284 * Writes the next chunk of snapshot data into the stream. Writing 285 * can be stopped by returning kAbort as function result. EndOfStream 286 * will not be called in case writing was aborted. 287 */ 288 virtual WriteResult WriteAsciiChunk(char* data, int size) = 0; 289 /** 290 * Writes the next chunk of heap stats data into the stream. Writing 291 * can be stopped by returning kAbort as function result. EndOfStream 292 * will not be called in case writing was aborted. 293 */ WriteHeapStatsChunk(HeapStatsUpdate * data,int count)294 virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) { 295 return kAbort; 296 } 297 }; 298 299 300 /** 301 * HeapSnapshots record the state of the JS heap at some moment. 302 */ 303 class V8_EXPORT HeapSnapshot { 304 public: 305 enum SerializationFormat { 306 kJSON = 0 // See format description near 'Serialize' method. 307 }; 308 309 /** Returns heap snapshot UID (assigned by the profiler.) */ 310 unsigned GetUid() const; 311 312 /** Returns heap snapshot title. */ 313 Handle<String> GetTitle() const; 314 315 /** Returns the root node of the heap graph. */ 316 const HeapGraphNode* GetRoot() const; 317 318 /** Returns a node by its id. */ 319 const HeapGraphNode* GetNodeById(SnapshotObjectId id) const; 320 321 /** Returns total nodes count in the snapshot. */ 322 int GetNodesCount() const; 323 324 /** Returns a node by index. */ 325 const HeapGraphNode* GetNode(int index) const; 326 327 /** Returns a max seen JS object Id. */ 328 SnapshotObjectId GetMaxSnapshotJSObjectId() const; 329 330 /** 331 * Deletes the snapshot and removes it from HeapProfiler's list. 332 * All pointers to nodes, edges and paths previously returned become 333 * invalid. 334 */ 335 void Delete(); 336 337 /** 338 * Prepare a serialized representation of the snapshot. The result 339 * is written into the stream provided in chunks of specified size. 340 * The total length of the serialized snapshot is unknown in 341 * advance, it can be roughly equal to JS heap size (that means, 342 * it can be really big - tens of megabytes). 343 * 344 * For the JSON format, heap contents are represented as an object 345 * with the following structure: 346 * 347 * { 348 * snapshot: { 349 * title: "...", 350 * uid: nnn, 351 * meta: { meta-info }, 352 * node_count: nnn, 353 * edge_count: nnn 354 * }, 355 * nodes: [nodes array], 356 * edges: [edges array], 357 * strings: [strings array] 358 * } 359 * 360 * Nodes reference strings, other nodes, and edges by their indexes 361 * in corresponding arrays. 362 */ 363 void Serialize(OutputStream* stream, SerializationFormat format) const; 364 }; 365 366 367 /** 368 * An interface for reporting progress and controlling long-running 369 * activities. 370 */ 371 class V8_EXPORT ActivityControl { // NOLINT 372 public: 373 enum ControlOption { 374 kContinue = 0, 375 kAbort = 1 376 }; ~ActivityControl()377 virtual ~ActivityControl() {} 378 /** 379 * Notify about current progress. The activity can be stopped by 380 * returning kAbort as the callback result. 381 */ 382 virtual ControlOption ReportProgressValue(int done, int total) = 0; 383 }; 384 385 386 /** 387 * Interface for controlling heap profiling. Instance of the 388 * profiler can be retrieved using v8::Isolate::GetHeapProfiler. 389 */ 390 class V8_EXPORT HeapProfiler { 391 public: 392 /** 393 * Callback function invoked for obtaining RetainedObjectInfo for 394 * the given JavaScript wrapper object. It is prohibited to enter V8 395 * while the callback is running: only getters on the handle and 396 * GetPointerFromInternalField on the objects are allowed. 397 */ 398 typedef RetainedObjectInfo* (*WrapperInfoCallback) 399 (uint16_t class_id, Handle<Value> wrapper); 400 401 /** Returns the number of snapshots taken. */ 402 int GetSnapshotCount(); 403 404 /** Returns a snapshot by index. */ 405 const HeapSnapshot* GetHeapSnapshot(int index); 406 407 /** 408 * Returns SnapshotObjectId for a heap object referenced by |value| if 409 * it has been seen by the heap profiler, kUnknownObjectId otherwise. 410 */ 411 SnapshotObjectId GetObjectId(Handle<Value> value); 412 413 /** 414 * Returns heap object with given SnapshotObjectId if the object is alive, 415 * otherwise empty handle is returned. 416 */ 417 Handle<Value> FindObjectById(SnapshotObjectId id); 418 419 /** 420 * Clears internal map from SnapshotObjectId to heap object. The new objects 421 * will not be added into it unless a heap snapshot is taken or heap object 422 * tracking is kicked off. 423 */ 424 void ClearObjectIds(); 425 426 /** 427 * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return 428 * it in case heap profiler cannot find id for the object passed as 429 * parameter. HeapSnapshot::GetNodeById will always return NULL for such id. 430 */ 431 static const SnapshotObjectId kUnknownObjectId = 0; 432 433 /** 434 * Callback interface for retrieving user friendly names of global objects. 435 */ 436 class ObjectNameResolver { 437 public: 438 /** 439 * Returns name to be used in the heap snapshot for given node. Returned 440 * string must stay alive until snapshot collection is completed. 441 */ 442 virtual const char* GetName(Handle<Object> object) = 0; 443 protected: ~ObjectNameResolver()444 virtual ~ObjectNameResolver() {} 445 }; 446 447 /** 448 * Takes a heap snapshot and returns it. Title may be an empty string. 449 */ 450 const HeapSnapshot* TakeHeapSnapshot( 451 Handle<String> title, 452 ActivityControl* control = NULL, 453 ObjectNameResolver* global_object_name_resolver = NULL); 454 455 /** 456 * Starts tracking of heap objects population statistics. After calling 457 * this method, all heap objects relocations done by the garbage collector 458 * are being registered. 459 * 460 * |track_allocations| parameter controls whether stack trace of each 461 * allocation in the heap will be recorded and reported as part of 462 * HeapSnapshot. 463 */ 464 void StartTrackingHeapObjects(bool track_allocations = false); 465 466 /** 467 * Adds a new time interval entry to the aggregated statistics array. The 468 * time interval entry contains information on the current heap objects 469 * population size. The method also updates aggregated statistics and 470 * reports updates for all previous time intervals via the OutputStream 471 * object. Updates on each time interval are provided as a stream of the 472 * HeapStatsUpdate structure instances. 473 * The return value of the function is the last seen heap object Id. 474 * 475 * StartTrackingHeapObjects must be called before the first call to this 476 * method. 477 */ 478 SnapshotObjectId GetHeapStats(OutputStream* stream); 479 480 /** 481 * Stops tracking of heap objects population statistics, cleans up all 482 * collected data. StartHeapObjectsTracking must be called again prior to 483 * calling PushHeapObjectsStats next time. 484 */ 485 void StopTrackingHeapObjects(); 486 487 /** 488 * Deletes all snapshots taken. All previously returned pointers to 489 * snapshots and their contents become invalid after this call. 490 */ 491 void DeleteAllHeapSnapshots(); 492 493 /** Binds a callback to embedder's class ID. */ 494 void SetWrapperClassInfoProvider( 495 uint16_t class_id, 496 WrapperInfoCallback callback); 497 498 /** 499 * Default value of persistent handle class ID. Must not be used to 500 * define a class. Can be used to reset a class of a persistent 501 * handle. 502 */ 503 static const uint16_t kPersistentHandleNoClassId = 0; 504 505 /** Returns memory used for profiler internal data and snapshots. */ 506 size_t GetProfilerMemorySize(); 507 508 /** 509 * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId). 510 */ 511 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info); 512 513 private: 514 HeapProfiler(); 515 ~HeapProfiler(); 516 HeapProfiler(const HeapProfiler&); 517 HeapProfiler& operator=(const HeapProfiler&); 518 }; 519 520 521 /** 522 * Interface for providing information about embedder's objects 523 * held by global handles. This information is reported in two ways: 524 * 525 * 1. When calling AddObjectGroup, an embedder may pass 526 * RetainedObjectInfo instance describing the group. To collect 527 * this information while taking a heap snapshot, V8 calls GC 528 * prologue and epilogue callbacks. 529 * 530 * 2. When a heap snapshot is collected, V8 additionally 531 * requests RetainedObjectInfos for persistent handles that 532 * were not previously reported via AddObjectGroup. 533 * 534 * Thus, if an embedder wants to provide information about native 535 * objects for heap snapshots, he can do it in a GC prologue 536 * handler, and / or by assigning wrapper class ids in the following way: 537 * 538 * 1. Bind a callback to class id by calling SetWrapperClassInfoProvider. 539 * 2. Call SetWrapperClassId on certain persistent handles. 540 * 541 * V8 takes ownership of RetainedObjectInfo instances passed to it and 542 * keeps them alive only during snapshot collection. Afterwards, they 543 * are freed by calling the Dispose class function. 544 */ 545 class V8_EXPORT RetainedObjectInfo { // NOLINT 546 public: 547 /** Called by V8 when it no longer needs an instance. */ 548 virtual void Dispose() = 0; 549 550 /** Returns whether two instances are equivalent. */ 551 virtual bool IsEquivalent(RetainedObjectInfo* other) = 0; 552 553 /** 554 * Returns hash value for the instance. Equivalent instances 555 * must have the same hash value. 556 */ 557 virtual intptr_t GetHash() = 0; 558 559 /** 560 * Returns human-readable label. It must be a null-terminated UTF-8 561 * encoded string. V8 copies its contents during a call to GetLabel. 562 */ 563 virtual const char* GetLabel() = 0; 564 565 /** 566 * Returns human-readable group label. It must be a null-terminated UTF-8 567 * encoded string. V8 copies its contents during a call to GetGroupLabel. 568 * Heap snapshot generator will collect all the group names, create 569 * top level entries with these names and attach the objects to the 570 * corresponding top level group objects. There is a default 571 * implementation which is required because embedders don't have their 572 * own implementation yet. 573 */ GetGroupLabel()574 virtual const char* GetGroupLabel() { return GetLabel(); } 575 576 /** 577 * Returns element count in case if a global handle retains 578 * a subgraph by holding one of its nodes. 579 */ GetElementCount()580 virtual intptr_t GetElementCount() { return -1; } 581 582 /** Returns embedder's object size in bytes. */ GetSizeInBytes()583 virtual intptr_t GetSizeInBytes() { return -1; } 584 585 protected: RetainedObjectInfo()586 RetainedObjectInfo() {} ~RetainedObjectInfo()587 virtual ~RetainedObjectInfo() {} 588 589 private: 590 RetainedObjectInfo(const RetainedObjectInfo&); 591 RetainedObjectInfo& operator=(const RetainedObjectInfo&); 592 }; 593 594 595 /** 596 * A struct for exporting HeapStats data from V8, using "push" model. 597 * See HeapProfiler::GetHeapStats. 598 */ 599 struct HeapStatsUpdate { HeapStatsUpdateHeapStatsUpdate600 HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size) 601 : index(index), count(count), size(size) { } 602 uint32_t index; // Index of the time interval that was changed. 603 uint32_t count; // New value of count field for the interval with this index. 604 uint32_t size; // New value of size field for the interval with this index. 605 }; 606 607 608 } // namespace v8 609 610 611 #endif // V8_V8_PROFILER_H_ 612