v8 14.1.146 (node 25.0.0)
V8 is Google's open source JavaScript engine
Loading...
Searching...
No Matches
v8-profiler.h
Go to the documentation of this file.
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 <limits.h>
9
10#include <memory>
11#include <unordered_set>
12#include <vector>
13
14#include "cppgc/common.h" // NOLINT(build/include_directory)
15#include "v8-local-handle.h" // NOLINT(build/include_directory)
16#include "v8-message.h" // NOLINT(build/include_directory)
17#include "v8-persistent-handle.h" // NOLINT(build/include_directory)
18
19/**
20 * Profiler support for the V8 JavaScript engine.
21 */
22namespace v8 {
23
24enum class EmbedderStateTag : uint8_t;
25class HeapGraphNode;
26struct HeapStatsUpdate;
27class Object;
28enum StateTag : uint16_t;
29
30using NativeObject = void*;
31using SnapshotObjectId = uint32_t;
32using ProfilerId = uint32_t;
33
37};
38
39namespace internal {
40class CpuProfile;
41} // namespace internal
42
43} // namespace v8
44
45#ifdef V8_OS_WIN
46template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
47#endif
48
49namespace v8 {
50
52 /** A pointer to a static string owned by v8. */
53 const char* deopt_reason;
55};
56
57} // namespace v8
58
59#ifdef V8_OS_WIN
60template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
61#endif
62
63namespace v8 {
64
65/**
66 * CpuProfileNode represents a node in a call graph.
67 */
69 public:
70 struct LineTick {
71 /** The 1-based number of the source line where the function originates. */
72 int line;
73
74 /** The 1-based number of the source column where the function originates.
75 */
76 int column;
77
78 /** The count of samples associated with the source line. */
79 unsigned int hit_count;
80 };
81
82 // An annotation hinting at the source of a CpuProfileNode.
84 // User-supplied script with associated resource information.
86 // Native scripts and provided builtins.
88 // Callbacks into native code.
90 // VM-internal functions or state.
92 // A node that failed to symbolize.
94 };
95
96 /** Returns function name (empty string for anonymous functions.) */
98
99 /**
100 * Returns function name (empty string for anonymous functions.)
101 * The string ownership is *not* passed to the caller. It stays valid until
102 * profile is deleted. The function is thread safe.
103 */
104 const char* GetFunctionNameStr() const;
105
106 /** Returns id of the script where function is located. */
107 int GetScriptId() const;
108
109 /** Returns resource name for script from where the function originates. */
111
112 /**
113 * Returns resource name for script from where the function originates.
114 * The string ownership is *not* passed to the caller. It stays valid until
115 * profile is deleted. The function is thread safe.
116 */
117 const char* GetScriptResourceNameStr() const;
118
119 /**
120 * Return true if the script from where the function originates is flagged as
121 * being shared cross-origin.
122 */
124
125 /**
126 * Returns the number, 1-based, of the line where the function originates.
127 * kNoLineNumberInfo if no line number information is available.
128 */
129 int GetLineNumber() const;
130
131 /**
132 * Returns 1-based number of the column where the function originates.
133 * kNoColumnNumberInfo if no column number information is available.
134 */
135 int GetColumnNumber() const;
136
137 /**
138 * Returns the number of the function's source lines that collect the samples.
139 */
140 unsigned int GetHitLineCount() const;
141
142 /** Returns the set of source lines that collect the samples.
143 * The caller allocates buffer and responsible for releasing it.
144 * True if all available entries are copied, otherwise false.
145 * The function copies nothing if buffer is not large enough.
146 */
147 bool GetLineTicks(LineTick* entries, unsigned int length) const;
148
149 /** Returns bailout reason for the function
150 * if the optimization was disabled for it.
151 */
152 const char* GetBailoutReason() const;
153
154 /**
155 * Returns the count of samples where the function was currently executing.
156 */
157 unsigned GetHitCount() const;
158
159 /** Returns id of the node. The id is unique within the tree */
160 unsigned GetNodeId() const;
161
162 /**
163 * Gets the type of the source which the node was captured from.
164 */
166
167 /** Returns child nodes count of the node. */
168 int GetChildrenCount() const;
169
170 /** Retrieves a child node by index. */
171 const CpuProfileNode* GetChild(int index) const;
172
173 /** Retrieves the ancestor node, or null if the root. */
174 const CpuProfileNode* GetParent() const;
175
176 /** Retrieves deopt infos for the node. */
178
181};
182
183/**
184 * An interface for exporting data from V8, using "push" model.
185 */
187 public:
188 enum WriteResult { kContinue = 0, kAbort = 1 };
189 virtual ~OutputStream() = default;
190 /** Notify about the end of stream. */
191 virtual void EndOfStream() = 0;
192 /** Get preferred output chunk size. Called only once. */
193 virtual int GetChunkSize() { return 1024; }
194 /**
195 * Writes the next chunk of snapshot data into the stream. Writing
196 * can be stopped by returning kAbort as function result. EndOfStream
197 * will not be called in case writing was aborted.
198 */
199 virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
200 /**
201 * Writes the next chunk of heap stats data into the stream. Writing
202 * can be stopped by returning kAbort as function result. EndOfStream
203 * will not be called in case writing was aborted.
204 */
206 return kAbort;
207 }
208};
209
210/**
211 * CpuProfile contains a CPU profile in a form of top-down call tree
212 * (from main() down to functions that do all the work).
213 */
215 public:
217 kJSON = 0 // See format description near 'Serialize' method.
218 };
219 /** Returns CPU profile title. */
221
222 /** Returns the root node of the top down call tree. */
224
225 /**
226 * Returns number of samples recorded. The samples are not recorded unless
227 * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
228 */
229 int GetSamplesCount() const;
230
231 /**
232 * Returns profile node corresponding to the top frame the sample at
233 * the given index.
234 */
235 const CpuProfileNode* GetSample(int index) const;
236
237 /**
238 * Returns the timestamp of the sample. The timestamp is the number of
239 * microseconds since some unspecified starting point.
240 * The point is equal to the starting point used by GetStartTime.
241 */
242 int64_t GetSampleTimestamp(int index) const;
243
244 /**
245 * Returns time when the profile recording was started (in microseconds)
246 * since some unspecified starting point.
247 */
248 int64_t GetStartTime() const;
249
250 /**
251 * Returns state of the vm when sample was captured.
252 */
253 StateTag GetSampleState(int index) const;
254
255 /**
256 * Returns state of the embedder when sample was captured.
257 */
259
260 /**
261 * Returns time when the profile recording was stopped (in microseconds)
262 * since some unspecified starting point.
263 * The point is equal to the starting point used by GetStartTime.
264 */
265 int64_t GetEndTime() const;
266
267 /**
268 * Deletes the profile and removes it from CpuProfiler's list.
269 * All pointers to nodes previously returned become invalid.
270 */
271 void Delete();
272
273 /**
274 * Prepare a serialized representation of the profile. The result
275 * is written into the stream provided in chunks of specified size.
276 *
277 * For the JSON format, heap contents are represented as an object
278 * with the following structure:
279 *
280 * {
281 * nodes: [nodes array],
282 * startTime: number,
283 * endTime: number
284 * samples: [strings array]
285 * timeDeltas: [numbers array]
286 * }
287 *
288 */
290 SerializationFormat format = kJSON) const;
291};
292
294 // In the resulting CpuProfile tree, intermediate nodes in a stack trace
295 // (from the root to a leaf) will have line numbers that point to the start
296 // line of the function, rather than the line of the callsite of the child.
298 // In the resulting CpuProfile tree, nodes are separated based on the line
299 // number of their callsite in their parent.
301};
302
303// Determines how names are derived for functions sampled.
305 // Use the immediate name of functions at compilation time.
307 // Use more verbose naming for functions without names, inferred from scope
308 // where possible.
310};
311
313 // Enables logging when a profile is active, and disables logging when all
314 // profiles are detached.
316 // Enables logging for the lifetime of the CpuProfiler. Calls to
317 // StartRecording are faster, at the expense of runtime overhead.
319};
320
321// Enum for returning profiling status. Once StartProfiling is called,
322// we want to return to clients whether the profiling was able to start
323// correctly, or return a descriptive error.
325 kStarted,
328};
329
330/**
331 * Result from StartProfiling returning the Profiling Status, and
332 * id of the started profiler, or 0 if profiler is not started
333 */
335 const ProfilerId id;
337};
338
339/**
340 * Delegate for when max samples reached and samples are discarded.
341 */
343 public:
345
346 virtual ~DiscardedSamplesDelegate() = default;
347 virtual void Notify() = 0;
348
349 ProfilerId GetId() const { return profiler_id_; }
350
351 private:
352 friend internal::CpuProfile;
353
354 void SetId(ProfilerId id) { profiler_id_ = id; }
355
356 ProfilerId profiler_id_;
357};
358
359/**
360 * Optional profiling attributes.
361 */
363 public:
364 // Indicates that the sample buffer size should not be explicitly limited.
365 static const unsigned kNoSampleLimit = UINT_MAX;
366
367 /**
368 * \param mode Type of computation of stack frame line numbers.
369 * \param max_samples The maximum number of samples that should be recorded by
370 * the profiler. Samples obtained after this limit will be
371 * discarded.
372 * \param sampling_interval_us controls the profile-specific target
373 * sampling interval. The provided sampling
374 * interval will be snapped to the next lowest
375 * non-zero multiple of the profiler's sampling
376 * interval, set via SetSamplingInterval(). If
377 * zero, the sampling interval will be equal to
378 * the profiler's sampling interval.
379 * \param filter_context If specified, profiles will only contain frames
380 * using this context. Other frames will be elided.
381 */
384 unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0,
385 MaybeLocal<Context> filter_context = MaybeLocal<Context>());
386
389
390 CpuProfilingMode mode() const { return mode_; }
391 unsigned max_samples() const { return max_samples_; }
392 int sampling_interval_us() const { return sampling_interval_us_; }
393
394 private:
395 friend class internal::CpuProfile;
396
397 bool has_filter_context() const { return !filter_context_.IsEmpty(); }
398 void* raw_filter_context() const;
399
400 CpuProfilingMode mode_;
401 unsigned max_samples_;
402 int sampling_interval_us_;
403 Global<Context> filter_context_;
404};
405
406/**
407 * Interface for controlling CPU profiling. Instance of the
408 * profiler can be created using v8::CpuProfiler::New method.
409 */
411 public:
412 /**
413 * Creates a new CPU profiler for the |isolate|. The isolate must be
414 * initialized. The profiler object must be disposed after use by calling
415 * |Dispose| method.
416 */
417 static CpuProfiler* New(Isolate* isolate,
420
421 /**
422 * Synchronously collect current stack sample in all profilers attached to
423 * the |isolate|. The call does not affect number of ticks recorded for
424 * the current top node.
425 * |trace_id| is an optional identifier set to the collected sample.
426 * this is useful to associate the sample with a trace event.
427 */
428 static void CollectSample(
429 Isolate* isolate, const std::optional<uint64_t> trace_id = std::nullopt);
430
431 /**
432 * Disposes the CPU profiler object.
433 */
434 void Dispose();
435
436 /**
437 * Changes default CPU profiler sampling interval to the specified number
438 * of microseconds. Default interval is 1000us. This method must be called
439 * when there are no profiles being recorded.
440 */
442
443 /**
444 * Sets whether or not the profiler should prioritize consistency of sample
445 * periodicity on Windows. Disabling this can greatly reduce CPU usage, but
446 * may result in greater variance in sample timings from the platform's
447 * scheduler. Defaults to enabled. This method must be called when there are
448 * no profiles being recorded.
449 */
451
452 /**
453 * Starts collecting a CPU profile. Several profiles may be collected at once.
454 * Generates an anonymous profiler, without a String identifier.
455 */
457 CpuProfilingOptions options,
458 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
459
460 /**
461 * Starts collecting a CPU profile. Title may be an empty string. Several
462 * profiles may be collected at once. Attempts to start collecting several
463 * profiles with the same title are silently ignored.
464 */
466 Local<String> title, CpuProfilingOptions options,
467 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
468
469 /**
470 * Starts profiling with the same semantics as above, except with expanded
471 * parameters.
472 *
473 * |record_samples| parameter controls whether individual samples should
474 * be recorded in addition to the aggregated tree.
475 *
476 * |max_samples| controls the maximum number of samples that should be
477 * recorded by the profiler. Samples obtained after this limit will be
478 * discarded.
479 */
481 Local<String> title, CpuProfilingMode mode, bool record_samples = false,
482 unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
483
484 /**
485 * The same as StartProfiling above, but the CpuProfilingMode defaults to
486 * kLeafNodeLineNumbers mode, which was the previous default behavior of the
487 * profiler.
488 */
489 CpuProfilingResult Start(Local<String> title, bool record_samples = false);
490
491 /**
492 * Starts collecting a CPU profile. Title may be an empty string. Several
493 * profiles may be collected at once. Attempts to start collecting several
494 * profiles with the same title are silently ignored.
495 */
497 Local<String> title, CpuProfilingOptions options,
498 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
499
500 /**
501 * Starts profiling with the same semantics as above, except with expanded
502 * parameters.
503 *
504 * |record_samples| parameter controls whether individual samples should
505 * be recorded in addition to the aggregated tree.
506 *
507 * |max_samples| controls the maximum number of samples that should be
508 * recorded by the profiler. Samples obtained after this limit will be
509 * discarded.
510 */
512 Local<String> title, CpuProfilingMode mode, bool record_samples = false,
513 unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
514
515 /**
516 * The same as StartProfiling above, but the CpuProfilingMode defaults to
517 * kLeafNodeLineNumbers mode, which was the previous default behavior of the
518 * profiler.
519 */
521 bool record_samples = false);
522
523 /**
524 * Stops collecting CPU profile with a given id and returns it.
525 */
526 CpuProfile* Stop(ProfilerId id);
527
528 /**
529 * Stops collecting CPU profile with a given title and returns it.
530 * If the title given is empty, finishes the last profile started.
531 */
533
534 /**
535 * Generate more detailed source positions to code objects. This results in
536 * better results when mapping profiling samples to script source.
537 */
539
540 private:
541 CpuProfiler();
542 ~CpuProfiler();
543 CpuProfiler(const CpuProfiler&);
544 CpuProfiler& operator=(const CpuProfiler&);
545};
546
547/**
548 * HeapSnapshotEdge represents a directed connection between heap
549 * graph nodes: from retainers to retained nodes.
550 */
552 public:
553 enum Type {
554 kContextVariable = 0, // A variable from a function context.
555 kElement = 1, // An element of an array.
556 kProperty = 2, // A named object property.
557 kInternal = 3, // A link that can't be accessed from JS,
558 // thus, its name isn't a real property name
559 // (e.g. parts of a ConsString).
560 kHidden = 4, // A link that is needed for proper sizes
561 // calculation, but may be hidden from user.
562 kShortcut = 5, // A link that must not be followed during
563 // sizes calculation.
564 kWeak = 6 // A weak reference (ignored by the GC).
565 };
566
567 /** Returns edge type (see HeapGraphEdge::Type). */
568 Type GetType() const;
569
570 /**
571 * Returns edge name. This can be a variable name, an element index, or
572 * a property name.
573 */
575
576 /** Returns origin node. */
578
579 /** Returns destination node. */
580 const HeapGraphNode* GetToNode() const;
581};
582
583
584/**
585 * HeapGraphNode represents a node in a heap graph.
586 */
588 public:
589 enum Type {
590 kHidden = 0, // Hidden node, may be filtered when shown to user.
591 kArray = 1, // An array of elements.
592 kString = 2, // A string.
593 kObject = 3, // A JS object (except for arrays and strings).
594 kCode = 4, // Compiled code.
595 kClosure = 5, // Function closure.
596 kRegExp = 6, // RegExp.
597 kHeapNumber = 7, // Number stored in the heap.
598 kNative = 8, // Native object (not from V8 heap).
599 kSynthetic = 9, // Synthetic object, usually used for grouping
600 // snapshot items together.
601 kConsString = 10, // Concatenated string. A pair of pointers to strings.
602 kSlicedString = 11, // Sliced string. A fragment of another string.
603 kSymbol = 12, // A Symbol (ES6).
604 kBigInt = 13, // BigInt.
605 kObjectShape = 14, // Internal data used for tracking the shapes (or
606 // "hidden classes") of JS objects.
607 };
608
609 /** Returns node type (see HeapGraphNode::Type). */
610 Type GetType() const;
611
612 /**
613 * Returns node name. Depending on node's type this can be the name
614 * of the constructor (for objects), the name of the function (for
615 * closures), string value, or an empty string (for compiled code).
616 */
618
619 /**
620 * Returns node id. For the same heap object, the id remains the same
621 * across all snapshots.
622 */
623 SnapshotObjectId GetId() const;
624
625 /** Returns node's own size, in bytes. */
627
628 /** Returns child nodes count of the node. */
629 int GetChildrenCount() const;
630
631 /** Retrieves a child by index. */
632 const HeapGraphEdge* GetChild(int index) const;
633};
634
635/**
636 * HeapSnapshots record the state of the JS heap at some moment.
637 */
639 public:
641 kJSON = 0 // See format description near 'Serialize' method.
642 };
643
644 /** Returns the root node of the heap graph. */
645 const HeapGraphNode* GetRoot() const;
646
647 /** Returns a node by its id. */
648 const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
649
650 /** Returns total nodes count in the snapshot. */
651 int GetNodesCount() const;
652
653 /** Returns a node by index. */
654 const HeapGraphNode* GetNode(int index) const;
655
656 /** Returns a max seen JS object Id. */
657 SnapshotObjectId GetMaxSnapshotJSObjectId() const;
658
659 /**
660 * Deletes the snapshot and removes it from HeapProfiler's list.
661 * All pointers to nodes, edges and paths previously returned become
662 * invalid.
663 */
664 void Delete();
665
666 /**
667 * Prepare a serialized representation of the snapshot. The result
668 * is written into the stream provided in chunks of specified size.
669 * The total length of the serialized snapshot is unknown in
670 * advance, it can be roughly equal to JS heap size (that means,
671 * it can be really big - tens of megabytes).
672 *
673 * For the JSON format, heap contents are represented as an object
674 * with the following structure:
675 *
676 * {
677 * snapshot: {
678 * title: "...",
679 * uid: nnn,
680 * meta: { meta-info },
681 * node_count: nnn,
682 * edge_count: nnn
683 * },
684 * nodes: [nodes array],
685 * edges: [edges array],
686 * strings: [strings array]
687 * }
688 *
689 * Nodes reference strings, other nodes, and edges by their indexes
690 * in corresponding arrays.
691 */
693 SerializationFormat format = kJSON) const;
694};
695
696
697/**
698 * An interface for reporting progress and controlling long-running
699 * activities.
700 */
702 public:
705 kAbort = 1
706 };
707 virtual ~ActivityControl() = default;
708 /**
709 * Notify about current progress. The activity can be stopped by
710 * returning kAbort as the callback result.
711 */
712 virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total) = 0;
713};
714
715/**
716 * AllocationProfile is a sampled profile of allocations done by the program.
717 * This is structured as a call-graph.
718 */
720 public:
721 struct Allocation {
722 /**
723 * Size of the sampled allocation object.
724 */
726
727 /**
728 * The number of objects of such size that were sampled.
729 */
730 unsigned int count;
731 };
732
733 /**
734 * Represents a node in the call-graph.
735 */
736 struct Node {
737 /**
738 * Name of the function. May be empty for anonymous functions or if the
739 * script corresponding to this function has been unloaded.
740 */
742
743 /**
744 * Name of the script containing the function. May be empty if the script
745 * name is not available, or if the script has been unloaded.
746 */
748
749 /**
750 * id of the script where the function is located. May be equal to
751 * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
752 */
754
755 /**
756 * Start position of the function in the script.
757 */
759
760 /**
761 * 1-indexed line number where the function starts. May be
762 * kNoLineNumberInfo if no line number information is available.
763 */
765
766 /**
767 * 1-indexed column number where the function starts. May be
768 * kNoColumnNumberInfo if no line number information is available.
769 */
771
772 /**
773 * Unique id of the node.
774 */
775 uint32_t node_id;
776
777 /**
778 * List of callees called from this node for which we have sampled
779 * allocations. The lifetime of the children is scoped to the containing
780 * AllocationProfile.
781 */
783
784 /**
785 * List of self allocations done by this node in the call-graph.
786 */
788 };
789
790 /**
791 * Represent a single sample recorded for an allocation.
792 */
793 struct Sample {
794 /**
795 * id of the node in the profile tree.
796 */
797 uint32_t node_id;
798
799 /**
800 * Size of the sampled allocation object.
801 */
803
804 /**
805 * The number of objects of such size that were sampled.
806 */
807 unsigned int count;
808
809 /**
810 * Unique time-ordered id of the allocation sample. Can be used to track
811 * what samples were added or removed between two snapshots.
812 */
813 uint64_t sample_id;
814 };
815
816 /**
817 * Returns the root node of the call-graph. The root node corresponds to an
818 * empty JS call-stack. The lifetime of the returned Node* is scoped to the
819 * containing AllocationProfile.
820 */
821 virtual Node* GetRootNode() = 0;
822 virtual const std::vector<Sample>& GetSamples() = 0;
823
824 virtual ~AllocationProfile() = default;
825
828};
829
830/**
831 * An object graph consisting of embedder objects and V8 objects.
832 * Edges of the graph are strong references between the objects.
833 * The embedder can build this graph during heap snapshot generation
834 * to include the embedder objects in the heap snapshot.
835 * Usage:
836 * 1) Define derived class of EmbedderGraph::Node for embedder objects.
837 * 2) Set the build embedder graph callback on the heap profiler using
838 * HeapProfiler::AddBuildEmbedderGraphCallback.
839 * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from
840 * node1 to node2.
841 * 4) To represent references from/to V8 object, construct V8 nodes using
842 * graph->V8Node(value).
843 */
845 public:
846 class Node {
847 public:
848 /**
849 * Detachedness specifies whether an object is attached or detached from the
850 * main application state. While unkown in general, there may be objects
851 * that specifically know their state. V8 passes this information along in
852 * the snapshot. Users of the snapshot may use it to annotate the object
853 * graph.
854 */
855 enum class Detachedness : uint8_t {
856 kUnknown = 0,
857 kAttached = 1,
858 kDetached = 2,
859 };
860
861 Node() = default;
862 virtual ~Node() = default;
863 virtual const char* Name() = 0;
864 virtual size_t SizeInBytes() = 0;
865 /**
866 * The corresponding V8 wrapper node if not null.
867 * During heap snapshot generation the embedder node and the V8 wrapper
868 * node will be merged into one node to simplify retaining paths.
869 */
870 virtual Node* WrapperNode() { return nullptr; }
871 virtual bool IsRootNode() { return false; }
872 /** Must return true for non-V8 nodes. */
873 virtual bool IsEmbedderNode() { return true; }
874 /**
875 * Optional name prefix. It is used in Chrome for tagging detached nodes.
876 */
877 virtual const char* NamePrefix() { return nullptr; }
878
879 /**
880 * Returns the NativeObject that can be used for querying the
881 * |HeapSnapshot|.
882 */
883 virtual NativeObject GetNativeObject() { return nullptr; }
884
885 /**
886 * Detachedness state of a given object. While unkown in general, there may
887 * be objects that specifically know their state. V8 passes this information
888 * along in the snapshot. Users of the snapshot may use it to annotate the
889 * object graph.
890 */
892
893 /**
894 * Returns the address of the object in the embedder heap, or nullptr to not
895 * specify the address. If this address is provided, then V8 can generate
896 * consistent IDs for objects across subsequent heap snapshots, which allows
897 * devtools to determine which objects were retained from one snapshot to
898 * the next. This value is used only if GetNativeObject returns nullptr.
899 */
900 virtual const void* GetAddress() { return nullptr; }
901
902 Node(const Node&) = delete;
903 Node& operator=(const Node&) = delete;
904 };
905
906 /**
907 * Returns a node corresponding to the given V8 value. Ownership is not
908 * transferred. The result pointer is valid while the graph is alive.
909 *
910 * For now the variant that takes v8::Data is not marked as abstract for
911 * compatibility, but embedders who subclass EmbedderGraph are expected to
912 * implement it. Then in the implementation of the variant that takes
913 * v8::Value, they can simply forward the call to the one that takes
914 * v8::Local<v8::Data>.
915 */
916 virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0;
917
918 /**
919 * Returns a node corresponding to the given V8 value. Ownership is not
920 * transferred. The result pointer is valid while the graph is alive.
921 *
922 * For API compatibility, this default implementation just checks that the
923 * data is a v8::Value and forward it to the variant that takes v8::Value,
924 * which is currently required to be implemented. In the future we'll remove
925 * the v8::Value variant, and make this variant that takes v8::Data abstract
926 * instead. If the embedder subclasses v8::EmbedderGraph and also use
927 * v8::TracedReference<v8::Data>, they must override this variant.
928 */
929 virtual Node* V8Node(const v8::Local<v8::Data>& value);
930
931 /**
932 * Adds the given node to the graph and takes ownership of the node.
933 * Returns a raw pointer to the node that is valid while the graph is alive.
934 */
935 virtual Node* AddNode(std::unique_ptr<Node> node) = 0;
936
937 /**
938 * Adds an edge that represents a strong reference from the given
939 * node |from| to the given node |to|. The nodes must be added to the graph
940 * before calling this function.
941 *
942 * If name is nullptr, the edge will have auto-increment indexes, otherwise
943 * it will be named accordingly.
944 */
945 virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0;
946
947 /**
948 * Adds a count of bytes that are not associated with any particular Node.
949 * An embedder may use this to represent the size of nodes which were omitted
950 * from this EmbedderGraph despite being retained by the graph, or other
951 * overhead costs. This number will contribute to the total size in a heap
952 * snapshot, without being represented in the object graph.
953 */
954 virtual void AddNativeSize(size_t size) {}
955
956 virtual ~EmbedderGraph() = default;
957};
958
960 public:
961 virtual ~QueryObjectPredicate() = default;
962 virtual bool Filter(v8::Local<v8::Object> object) = 0;
963};
964
965/**
966 * Interface for controlling heap profiling. Instance of the
967 * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
968 */
970 public:
971 void QueryObjects(v8::Local<v8::Context> context,
972 QueryObjectPredicate* predicate,
973 std::vector<v8::Global<v8::Object>>* objects);
974
980 };
981
982 /**
983 * Callback function invoked during heap snapshot generation to retrieve
984 * the embedder object graph. The callback should use graph->AddEdge(..) to
985 * add references between the objects.
986 * The callback must not trigger garbage collection in V8.
987 */
988 typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate,
989 v8::EmbedderGraph* graph,
990 void* data);
991
992 /**
993 * Callback function invoked during heap snapshot generation to retrieve
994 * the detachedness state of a JS object referenced by a TracedReference.
995 *
996 * The callback takes Local<Value> as parameter to allow the embedder to
997 * unpack the TracedReference into a Local and reuse that Local for different
998 * purposes.
999 */
1000 using GetDetachednessCallback = EmbedderGraph::Node::Detachedness (*)(
1001 v8::Isolate* isolate, const v8::Local<v8::Value>& v8_value,
1002 uint16_t class_id, void* data);
1003
1004 /** Returns the number of snapshots taken. */
1006
1007 /** Returns a snapshot by index. */
1009
1010 /**
1011 * Returns SnapshotObjectId for a heap object referenced by |value| if
1012 * it has been seen by the heap profiler, kUnknownObjectId otherwise.
1013 */
1014 SnapshotObjectId GetObjectId(Local<Value> value);
1015
1016 /**
1017 * Returns SnapshotObjectId for a native object referenced by |value| if it
1018 * has been seen by the heap profiler, kUnknownObjectId otherwise.
1019 */
1020 SnapshotObjectId GetObjectId(NativeObject value);
1021
1022 /**
1023 * Returns heap object with given SnapshotObjectId if the object is alive,
1024 * otherwise empty handle is returned.
1025 */
1026 Local<Value> FindObjectById(SnapshotObjectId id);
1027
1028 /**
1029 * Clears internal map from SnapshotObjectId to heap object. The new objects
1030 * will not be added into it unless a heap snapshot is taken or heap object
1031 * tracking is kicked off.
1032 */
1034
1035 /**
1036 * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
1037 * it in case heap profiler cannot find id for the object passed as
1038 * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
1039 */
1040 static const SnapshotObjectId kUnknownObjectId = 0;
1041
1042 /**
1043 * Callback interface for retrieving user friendly names of global objects.
1044 */
1046 public:
1047 /**
1048 * Returns name to be used in the heap snapshot for given node. Returned
1049 * string must stay alive until snapshot collection is completed.
1050 */
1051 virtual const char* GetName(Local<Object> object) = 0;
1052
1053 protected:
1054 virtual ~ObjectNameResolver() = default;
1055 };
1056
1057 enum class HeapSnapshotMode {
1058 /**
1059 * Heap snapshot for regular developers.
1060 */
1061 kRegular,
1062 /**
1063 * Heap snapshot is exposing internals that may be useful for experts.
1064 */
1066 };
1067
1068 enum class NumericsMode {
1069 /**
1070 * Numeric values are hidden as they are values of the corresponding
1071 * objects.
1072 */
1074 /**
1075 * Numeric values are exposed in artificial fields.
1076 */
1078 };
1079
1080 struct HeapSnapshotOptions final {
1081 // Manually define default constructor here to be able to use it in
1082 // `TakeSnapshot()` below.
1083 // NOLINTNEXTLINE
1085
1086 /**
1087 * The control used to report intermediate progress to.
1088 */
1090 /**
1091 * The resolver used by the snapshot generator to get names for V8 objects.
1092 */
1094 /**
1095 * Mode for taking the snapshot, see `HeapSnapshotMode`.
1096 */
1098 /**
1099 * Mode for dealing with numeric values, see `NumericsMode`.
1100 */
1102 /**
1103 * Whether stack is considered as a root set.
1104 */
1107 };
1108
1109 /**
1110 * Takes a heap snapshot.
1111 *
1112 * \returns the snapshot.
1113 */
1115 const HeapSnapshotOptions& options = HeapSnapshotOptions());
1116
1117 /**
1118 * Takes a heap snapshot. See `HeapSnapshotOptions` for details on the
1119 * parameters.
1120 *
1121 * \returns the snapshot.
1122 */
1124 ActivityControl* control,
1125 ObjectNameResolver* global_object_name_resolver = nullptr,
1126 bool hide_internals = true, bool capture_numeric_value = false);
1127
1128 /**
1129 * Obtains list of Detached JS Wrapper Objects. This functon calls garbage
1130 * collection, then iterates over traced handles in the isolate
1131 */
1133
1134 /**
1135 * Starts tracking of heap objects population statistics. After calling
1136 * this method, all heap objects relocations done by the garbage collector
1137 * are being registered.
1138 *
1139 * |track_allocations| parameter controls whether stack trace of each
1140 * allocation in the heap will be recorded and reported as part of
1141 * HeapSnapshot.
1142 */
1143 void StartTrackingHeapObjects(bool track_allocations = false);
1144
1145 /**
1146 * Adds a new time interval entry to the aggregated statistics array. The
1147 * time interval entry contains information on the current heap objects
1148 * population size. The method also updates aggregated statistics and
1149 * reports updates for all previous time intervals via the OutputStream
1150 * object. Updates on each time interval are provided as a stream of the
1151 * HeapStatsUpdate structure instances.
1152 * If |timestamp_us| is supplied, timestamp of the new entry will be written
1153 * into it. The return value of the function is the last seen heap object Id.
1154 *
1155 * StartTrackingHeapObjects must be called before the first call to this
1156 * method.
1157 */
1158 SnapshotObjectId GetHeapStats(OutputStream* stream,
1159 int64_t* timestamp_us = nullptr);
1160
1161 /**
1162 * Stops tracking of heap objects population statistics, cleans up all
1163 * collected data. StartHeapObjectsTracking must be called again prior to
1164 * calling GetHeapStats next time.
1165 */
1167
1168 /**
1169 * Starts gathering a sampling heap profile. A sampling heap profile is
1170 * similar to tcmalloc's heap profiler and Go's mprof. It samples object
1171 * allocations and builds an online 'sampling' heap profile. At any point in
1172 * time, this profile is expected to be a representative sample of objects
1173 * currently live in the system. Each sampled allocation includes the stack
1174 * trace at the time of allocation, which makes this really useful for memory
1175 * leak detection.
1176 *
1177 * This mechanism is intended to be cheap enough that it can be used in
1178 * production with minimal performance overhead.
1179 *
1180 * Allocations are sampled using a randomized Poisson process. On average, one
1181 * allocation will be sampled every |sample_interval| bytes allocated. The
1182 * |stack_depth| parameter controls the maximum number of stack frames to be
1183 * captured on each allocation.
1184 *
1185 * NOTE: Support for native allocations doesn't exist yet, but is anticipated
1186 * in the future.
1187 *
1188 * Objects allocated before the sampling is started will not be included in
1189 * the profile.
1190 *
1191 * Returns false if a sampling heap profiler is already running.
1192 */
1193 bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
1194 int stack_depth = 16,
1196
1197 /**
1198 * Stops the sampling heap profile and discards the current profile.
1199 */
1201
1202 /**
1203 * Returns the sampled profile of allocations allocated (and still live) since
1204 * StartSamplingHeapProfiler was called. The ownership of the pointer is
1205 * transferred to the caller. Returns nullptr if sampling heap profiler is not
1206 * active.
1207 */
1209
1210 /**
1211 * Deletes all snapshots taken. All previously returned pointers to
1212 * snapshots and their contents become invalid after this call.
1213 */
1215
1217 void* data);
1219 void* data);
1220
1221 void SetGetDetachednessCallback(GetDetachednessCallback callback, void* data);
1222
1223 /**
1224 * Returns whether the heap profiler is currently taking a snapshot.
1225 */
1227
1228 /**
1229 * Allocates a copy of the provided string within the heap snapshot generator
1230 * and returns a pointer to the copy. May only be called during heap snapshot
1231 * generation.
1232 */
1233 const char* CopyNameForHeapSnapshot(const char* name);
1234
1235 /**
1236 * Default value of persistent handle class ID. Must not be used to
1237 * define a class. Can be used to reset a class of a persistent
1238 * handle.
1239 */
1240 static const uint16_t kPersistentHandleNoClassId = 0;
1241
1242 private:
1243 HeapProfiler();
1244 ~HeapProfiler();
1245 HeapProfiler(const HeapProfiler&);
1246 HeapProfiler& operator=(const HeapProfiler&);
1247};
1248
1249/**
1250 * A struct for exporting HeapStats data from V8, using "push" model.
1251 * See HeapProfiler::GetHeapStats.
1252 */
1254 HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
1255 : index(index), count(count), size(size) { }
1256 uint32_t index; // Index of the time interval that was changed.
1257 uint32_t count; // New value of count field for the interval with this index.
1258 uint32_t size; // New value of size field for the interval with this index.
1259};
1260
1261#define CODE_EVENTS_LIST(V)
1262 V(Builtin)
1263 V(Callback)
1264 V(Eval)
1265 V(Function)
1266 V(InterpretedFunction)
1267 V(Handler)
1268 V(BytecodeHandler)
1269 V(LazyCompile) /* Unused, use kFunction instead */
1270 V(RegExp)
1271 V(Script)
1272 V(Stub)
1273 V(Relocation)
1274
1275/**
1276 * Note that this enum may be extended in the future. Please include a default
1277 * case if this enum is used in a switch statement.
1278 */
1280 kUnknownType = 0
1281#define V(Name) , k##Name##Type
1283#undef V
1285
1286/**
1287 * Representation of a code creation event
1288 */
1290 public:
1297 /**
1298 * NOTE (mmarchini): We can't allocate objects in the heap when we collect
1299 * existing code, and both the code type and the comment are not stored in the
1300 * heap, so we return those as const char*.
1301 */
1303 const char* GetComment();
1304
1305 static const char* GetCodeEventTypeName(CodeEventType code_event_type);
1306
1308};
1309
1310/**
1311 * Interface to listen to code creation and code relocation events.
1312 */
1314 public:
1315 /**
1316 * Creates a new listener for the |isolate|. The isolate must be initialized.
1317 * The listener object must be disposed after use by calling |Dispose| method.
1318 * Multiple listeners can be created for the same isolate.
1319 */
1320 explicit CodeEventHandler(Isolate* isolate);
1322
1323 /**
1324 * Handle is called every time a code object is created or moved. Information
1325 * about each code event will be available through the `code_event`
1326 * parameter.
1327 *
1328 * When the CodeEventType is kRelocationType, the code for this CodeEvent has
1329 * moved from `GetPreviousCodeStartAddress()` to `GetCodeStartAddress()`.
1330 */
1331 virtual void Handle(CodeEvent* code_event) = 0;
1332
1333 /**
1334 * Call `Enable()` to starts listening to code creation and code relocation
1335 * events. These events will be handled by `Handle()`.
1336 */
1337 void Enable();
1338
1339 /**
1340 * Call `Disable()` to stop listening to code creation and code relocation
1341 * events.
1342 */
1343 void Disable();
1344
1345 private:
1346 CodeEventHandler();
1347 CodeEventHandler(const CodeEventHandler&);
1348 CodeEventHandler& operator=(const CodeEventHandler&);
1349 void* internal_listener_;
1350};
1351
1352} // namespace v8
1353
1354
1355#endif // V8_V8_PROFILER_H_
virtual ~ActivityControl()=default
virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total)=0
virtual ~AllocationProfile()=default
static const int kNoColumnNumberInfo
virtual Node * GetRootNode()=0
static const int kNoLineNumberInfo
virtual const std::vector< Sample > & GetSamples()=0
virtual void Handle(CodeEvent *code_event)=0
virtual ~CodeEventHandler()
CodeEventHandler(Isolate *isolate)
int GetScriptLine()
CodeEventType GetCodeType()
size_t GetCodeSize()
Local< String > GetFunctionName()
int GetScriptColumn()
Local< String > GetScriptName()
uintptr_t GetCodeStartAddress()
const char * GetComment()
static const char * GetCodeEventTypeName(CodeEventType code_event_type)
uintptr_t GetPreviousCodeStartAddress()
int64_t GetStartTime() const
StateTag GetSampleState(int index) const
const CpuProfileNode * GetTopDownRoot() const
EmbedderStateTag GetSampleEmbedderState(int index) const
void Serialize(OutputStream *stream, SerializationFormat format=kJSON) const
int64_t GetSampleTimestamp(int index) const
Local< String > GetTitle() const
int GetSamplesCount() const
int64_t GetEndTime() const
const CpuProfileNode * GetSample(int index) const
const char * GetBailoutReason() const
const CpuProfileNode * GetParent() const
static const int kNoColumnNumberInfo
Local< String > GetFunctionName() const
static const int kNoLineNumberInfo
int GetChildrenCount() const
const std::vector< CpuProfileDeoptInfo > & GetDeoptInfos() const
unsigned GetNodeId() const
const char * GetScriptResourceNameStr() const
bool IsScriptSharedCrossOrigin() const
Local< String > GetScriptResourceName() const
bool GetLineTicks(LineTick *entries, unsigned int length) const
int GetLineNumber() const
const CpuProfileNode * GetChild(int index) const
int GetColumnNumber() const
unsigned int GetHitLineCount() const
int GetScriptId() const
SourceType GetSourceType() const
const char * GetFunctionNameStr() const
unsigned GetHitCount() const
static void CollectSample(Isolate *isolate, const std::optional< uint64_t > trace_id=std::nullopt)
CpuProfilingResult Start(Local< String > title, bool record_samples=false)
CpuProfile * StopProfiling(Local< String > title)
CpuProfilingResult Start(Local< String > title, CpuProfilingOptions options, std::unique_ptr< DiscardedSamplesDelegate > delegate=nullptr)
CpuProfilingResult Start(Local< String > title, CpuProfilingMode mode, bool record_samples=false, unsigned max_samples=CpuProfilingOptions::kNoSampleLimit)
CpuProfile * Stop(ProfilerId id)
void SetSamplingInterval(int us)
CpuProfilingStatus StartProfiling(Local< String > title, CpuProfilingMode mode, bool record_samples=false, unsigned max_samples=CpuProfilingOptions::kNoSampleLimit)
CpuProfilingStatus StartProfiling(Local< String > title, bool record_samples=false)
static void UseDetailedSourcePositionsForProfiling(Isolate *isolate)
void SetUsePreciseSampling(bool)
CpuProfilingStatus StartProfiling(Local< String > title, CpuProfilingOptions options, std::unique_ptr< DiscardedSamplesDelegate > delegate=nullptr)
CpuProfilingResult Start(CpuProfilingOptions options, std::unique_ptr< DiscardedSamplesDelegate > delegate=nullptr)
static CpuProfiler * New(Isolate *isolate, CpuProfilingNamingMode=kDebugNaming, CpuProfilingLoggingMode=kLazyLogging)
static const unsigned kNoSampleLimit
unsigned max_samples() const
CpuProfilingOptions & operator=(CpuProfilingOptions &&)=default
CpuProfilingMode mode() const
int sampling_interval_us() const
CpuProfilingOptions(CpuProfilingMode mode=kLeafNodeLineNumbers, unsigned max_samples=kNoSampleLimit, int sampling_interval_us=0, MaybeLocal< Context > filter_context=MaybeLocal< Context >())
CpuProfilingOptions(CpuProfilingOptions &&)=default
virtual ~DiscardedSamplesDelegate()=default
ProfilerId GetId() const
virtual const char * NamePrefix()
virtual const char * Name()=0
virtual bool IsRootNode()
virtual Node * WrapperNode()
Node & operator=(const Node &)=delete
Node(const Node &)=delete
virtual const void * GetAddress()
virtual NativeObject GetNativeObject()
virtual ~Node()=default
virtual Detachedness GetDetachedness()
virtual size_t SizeInBytes()=0
virtual bool IsEmbedderNode()
virtual Node * V8Node(const v8::Local< v8::Value > &value)=0
virtual ~EmbedderGraph()=default
virtual void AddEdge(Node *from, Node *to, const char *name=nullptr)=0
virtual Node * AddNode(std::unique_ptr< Node > node)=0
virtual Node * V8Node(const v8::Local< v8::Data > &value)
virtual void AddNativeSize(size_t size)
const HeapGraphNode * GetToNode() const
Type GetType() const
Local< Value > GetName() const
const HeapGraphNode * GetFromNode() const
const HeapGraphEdge * GetChild(int index) const
Type GetType() const
SnapshotObjectId GetId() const
int GetChildrenCount() const
Local< String > GetName() const
size_t GetShallowSize() const
virtual const char * GetName(Local< Object > object)=0
const HeapSnapshot * TakeHeapSnapshot(ActivityControl *control, ObjectNameResolver *global_object_name_resolver=nullptr, bool hide_internals=true, bool capture_numeric_value=false)
bool StartSamplingHeapProfiler(uint64_t sample_interval=512 *1024, int stack_depth=16, SamplingFlags flags=kSamplingNoFlags)
SnapshotObjectId GetObjectId(Local< Value > value)
const HeapSnapshot * TakeHeapSnapshot(const HeapSnapshotOptions &options=HeapSnapshotOptions())
void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, void *data)
void DeleteAllHeapSnapshots()
static const SnapshotObjectId kUnknownObjectId
const char * CopyNameForHeapSnapshot(const char *name)
AllocationProfile * GetAllocationProfile()
void StopTrackingHeapObjects()
static const uint16_t kPersistentHandleNoClassId
@ kSamplingIncludeObjectsCollectedByMinorGC
@ kSamplingIncludeObjectsCollectedByMajorGC
std::vector< v8::Local< v8::Value > > GetDetachedJSWrapperObjects()
void SetGetDetachednessCallback(GetDetachednessCallback callback, void *data)
void QueryObjects(v8::Local< v8::Context > context, QueryObjectPredicate *predicate, std::vector< v8::Global< v8::Object > > *objects)
SnapshotObjectId GetHeapStats(OutputStream *stream, int64_t *timestamp_us=nullptr)
const HeapSnapshot * GetHeapSnapshot(int index)
Local< Value > FindObjectById(SnapshotObjectId id)
void StartTrackingHeapObjects(bool track_allocations=false)
bool IsTakingSnapshot()
void StopSamplingHeapProfiler()
SnapshotObjectId GetObjectId(NativeObject value)
void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, void *data)
void(* BuildEmbedderGraphCallback)(v8::Isolate *isolate, v8::EmbedderGraph *graph, void *data)
const HeapGraphNode * GetNodeById(SnapshotObjectId id) const
SnapshotObjectId GetMaxSnapshotJSObjectId() const
const HeapGraphNode * GetNode(int index) const
void Serialize(OutputStream *stream, SerializationFormat format=kJSON) const
int GetNodesCount() const
const HeapGraphNode * GetRoot() const
friend class Local
friend class MaybeLocal
friend class Global
static const int kNoColumnInfo
Definition v8-message.h:202
static const int kNoLineNumberInfo
Definition v8-message.h:201
virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate *data, int count)
virtual WriteResult WriteAsciiChunk(char *data, int size)=0
virtual int GetChunkSize()
virtual void EndOfStream()=0
virtual ~OutputStream()=default
virtual bool Filter(v8::Local< v8::Object > object)=0
virtual ~QueryObjectPredicate()=default
EmbedderStackState
Definition common.h:15
CpuProfilingStatus
CpuProfilingLoggingMode
@ kLazyLogging
@ kEagerLogging
CpuProfilingMode
@ kLeafNodeLineNumbers
@ kCallerLineNumbers
StateTag
Definition v8-unwinder.h:39
CodeEventType
@ kUnknownType
CpuProfilingNamingMode
@ kDebugNaming
@ kStandardNaming
std::vector< Node * > children
Local< String > script_name
std::vector< Allocation > allocations
const char * deopt_reason
Definition v8-profiler.h:53
std::vector< CpuProfileDeoptFrame > stack
Definition v8-profiler.h:54
const CpuProfilingStatus status
const ProfilerId id
ObjectNameResolver * global_object_name_resolver
cppgc::EmbedderStackState stack_state
HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
#define CODE_EVENTS_LIST(V)
#define V8_EXPORT
Definition v8config.h:860