v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
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
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
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
53 const char* deopt_reason;
54 std::vector<CpuProfileDeoptFrame> stack;
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
69 public:
70 struct LineTick {
72 int line;
73
75 unsigned int hit_count;
76 };
77
78 // An annotation hinting at the source of a CpuProfileNode.
80 // User-supplied script with associated resource information.
81 kScript = 0,
82 // Native scripts and provided builtins.
83 kBuiltin = 1,
84 // Callbacks into native code.
85 kCallback = 2,
86 // VM-internal functions or state.
87 kInternal = 3,
88 // A node that failed to symbolize.
89 kUnresolved = 4,
90 };
91
93 Local<String> GetFunctionName() const;
94
100 const char* GetFunctionNameStr() const;
101
103 int GetScriptId() const;
104
106 Local<String> GetScriptResourceName() const;
107
113 const char* GetScriptResourceNameStr() const;
114
119 bool IsScriptSharedCrossOrigin() const;
120
125 int GetLineNumber() const;
126
131 int GetColumnNumber() const;
132
136 unsigned int GetHitLineCount() const;
137
143 bool GetLineTicks(LineTick* entries, unsigned int length) const;
144
148 const char* GetBailoutReason() const;
149
153 unsigned GetHitCount() const;
154
156 unsigned GetNodeId() const;
157
161 SourceType GetSourceType() const;
162
164 int GetChildrenCount() const;
165
167 const CpuProfileNode* GetChild(int index) const;
168
170 const CpuProfileNode* GetParent() const;
171
173 const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
174
175 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
176 static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
177};
178
183 public:
184 enum WriteResult { kContinue = 0, kAbort = 1 };
185 virtual ~OutputStream() = default;
187 virtual void EndOfStream() = 0;
189 virtual int GetChunkSize() { return 1024; }
195 virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
202 return kAbort;
203 }
204};
205
211 public:
213 kJSON = 0 // See format description near 'Serialize' method.
214 };
216 Local<String> GetTitle() const;
217
219 const CpuProfileNode* GetTopDownRoot() const;
220
225 int GetSamplesCount() const;
226
231 const CpuProfileNode* GetSample(int index) const;
232
238 int64_t GetSampleTimestamp(int index) const;
239
244 int64_t GetStartTime() const;
245
249 StateTag GetSampleState(int index) const;
250
254 EmbedderStateTag GetSampleEmbedderState(int index) const;
255
261 int64_t GetEndTime() const;
262
267 void Delete();
268
285 void Serialize(OutputStream* stream,
286 SerializationFormat format = kJSON) const;
287};
288
290 // In the resulting CpuProfile tree, intermediate nodes in a stack trace
291 // (from the root to a leaf) will have line numbers that point to the start
292 // line of the function, rather than the line of the callsite of the child.
294 // In the resulting CpuProfile tree, nodes are separated based on the line
295 // number of their callsite in their parent.
297};
298
299// Determines how names are derived for functions sampled.
301 // Use the immediate name of functions at compilation time.
303 // Use more verbose naming for functions without names, inferred from scope
304 // where possible.
306};
307
309 // Enables logging when a profile is active, and disables logging when all
310 // profiles are detached.
312 // Enables logging for the lifetime of the CpuProfiler. Calls to
313 // StartRecording are faster, at the expense of runtime overhead.
315};
316
317// Enum for returning profiling status. Once StartProfiling is called,
318// we want to return to clients whether the profiling was able to start
319// correctly, or return a descriptive error.
325
334
339 public:
341
342 virtual ~DiscardedSamplesDelegate() = default;
343 virtual void Notify() = 0;
344
345 ProfilerId GetId() const { return profiler_id_; }
346
347 private:
349
350 void SetId(ProfilerId id) { profiler_id_ = id; }
351
353};
354
359 public:
360 // Indicates that the sample buffer size should not be explicitly limited.
361 static const unsigned kNoSampleLimit = UINT_MAX;
362
379 CpuProfilingMode mode = kLeafNodeLineNumbers,
380 unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0,
381 MaybeLocal<Context> filter_context = MaybeLocal<Context>());
382
385
386 CpuProfilingMode mode() const { return mode_; }
387 unsigned max_samples() const { return max_samples_; }
388 int sampling_interval_us() const { return sampling_interval_us_; }
389
390 private:
392
393 bool has_filter_context() const { return !filter_context_.IsEmpty(); }
394 void* raw_filter_context() const;
395
397 unsigned max_samples_;
400};
401
407 public:
413 static CpuProfiler* New(Isolate* isolate,
416
424 static void CollectSample(
425 Isolate* isolate, const std::optional<uint64_t> trace_id = std::nullopt);
426
430 void Dispose();
431
437 void SetSamplingInterval(int us);
438
446 void SetUsePreciseSampling(bool);
447
452 CpuProfilingResult Start(
453 CpuProfilingOptions options,
454 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
455
461 CpuProfilingResult Start(
462 Local<String> title, CpuProfilingOptions options,
463 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
464
476 CpuProfilingResult Start(
477 Local<String> title, CpuProfilingMode mode, bool record_samples = false,
478 unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
479
485 CpuProfilingResult Start(Local<String> title, bool record_samples = false);
486
492 CpuProfilingStatus StartProfiling(
493 Local<String> title, CpuProfilingOptions options,
494 std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
495
507 CpuProfilingStatus StartProfiling(
508 Local<String> title, CpuProfilingMode mode, bool record_samples = false,
509 unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
510
516 CpuProfilingStatus StartProfiling(Local<String> title,
517 bool record_samples = false);
518
522 CpuProfile* Stop(ProfilerId id);
523
528 CpuProfile* StopProfiling(Local<String> title);
529
534 static void UseDetailedSourcePositionsForProfiling(Isolate* isolate);
535
536 private:
541};
542
548 public:
549 enum Type {
550 kContextVariable = 0, // A variable from a function context.
551 kElement = 1, // An element of an array.
552 kProperty = 2, // A named object property.
553 kInternal = 3, // A link that can't be accessed from JS,
554 // thus, its name isn't a real property name
555 // (e.g. parts of a ConsString).
556 kHidden = 4, // A link that is needed for proper sizes
557 // calculation, but may be hidden from user.
558 kShortcut = 5, // A link that must not be followed during
559 // sizes calculation.
560 kWeak = 6 // A weak reference (ignored by the GC).
561 };
562
564 Type GetType() const;
565
570 Local<Value> GetName() const;
571
573 const HeapGraphNode* GetFromNode() const;
574
576 const HeapGraphNode* GetToNode() const;
577};
578
579
584 public:
585 enum Type {
586 kHidden = 0, // Hidden node, may be filtered when shown to user.
587 kArray = 1, // An array of elements.
588 kString = 2, // A string.
589 kObject = 3, // A JS object (except for arrays and strings).
590 kCode = 4, // Compiled code.
591 kClosure = 5, // Function closure.
592 kRegExp = 6, // RegExp.
593 kHeapNumber = 7, // Number stored in the heap.
594 kNative = 8, // Native object (not from V8 heap).
595 kSynthetic = 9, // Synthetic object, usually used for grouping
596 // snapshot items together.
597 kConsString = 10, // Concatenated string. A pair of pointers to strings.
598 kSlicedString = 11, // Sliced string. A fragment of another string.
599 kSymbol = 12, // A Symbol (ES6).
600 kBigInt = 13, // BigInt.
601 kObjectShape = 14, // Internal data used for tracking the shapes (or
602 // "hidden classes") of JS objects.
603 };
604
606 Type GetType() const;
607
613 Local<String> GetName() const;
614
619 SnapshotObjectId GetId() const;
620
622 size_t GetShallowSize() const;
623
625 int GetChildrenCount() const;
626
628 const HeapGraphEdge* GetChild(int index) const;
629};
630
635 public:
637 kJSON = 0 // See format description near 'Serialize' method.
638 };
639
641 const HeapGraphNode* GetRoot() const;
642
644 const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
645
647 int GetNodesCount() const;
648
650 const HeapGraphNode* GetNode(int index) const;
651
653 SnapshotObjectId GetMaxSnapshotJSObjectId() const;
654
660 void Delete();
661
688 void Serialize(OutputStream* stream,
689 SerializationFormat format = kJSON) const;
690};
691
692
698 public:
700 kContinue = 0,
701 kAbort = 1
702 };
703 virtual ~ActivityControl() = default;
708 virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total) = 0;
709};
710
716 public:
717 struct Allocation {
721 size_t size;
722
726 unsigned int count;
727 };
728
732 struct Node {
738
744
750
755
761
767
771 uint32_t node_id;
772
778 std::vector<Node*> children;
779
783 std::vector<Allocation> allocations;
784 };
785
789 struct Sample {
793 uint32_t node_id;
794
798 size_t size;
799
803 unsigned int count;
804
809 uint64_t sample_id;
810 };
811
817 virtual Node* GetRootNode() = 0;
818 virtual const std::vector<Sample>& GetSamples() = 0;
819
820 virtual ~AllocationProfile() = default;
821
822 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
823 static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
824};
825
841 public:
842 class Node {
843 public:
851 enum class Detachedness : uint8_t {
852 kUnknown = 0,
853 kAttached = 1,
854 kDetached = 2,
855 };
856
857 Node() = default;
858 virtual ~Node() = default;
859 virtual const char* Name() = 0;
860 virtual size_t SizeInBytes() = 0;
866 virtual Node* WrapperNode() { return nullptr; }
867 virtual bool IsRootNode() { return false; }
869 virtual bool IsEmbedderNode() { return true; }
873 virtual const char* NamePrefix() { return nullptr; }
874
879 virtual NativeObject GetNativeObject() { return nullptr; }
880
887 virtual Detachedness GetDetachedness() { return Detachedness::kUnknown; }
888
896 virtual const void* GetAddress() { return nullptr; }
897
898 Node(const Node&) = delete;
899 Node& operator=(const Node&) = delete;
900 };
901
912 virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0;
913
925 virtual Node* V8Node(const v8::Local<v8::Data>& value);
926
931 virtual Node* AddNode(std::unique_ptr<Node> node) = 0;
932
941 virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0;
942
950 virtual void AddNativeSize(size_t size) {}
951
952 virtual ~EmbedderGraph() = default;
953};
954
956 public:
957 virtual ~QueryObjectPredicate() = default;
958 virtual bool Filter(v8::Local<v8::Object> object) = 0;
959};
960
966 public:
967 void QueryObjects(v8::Local<v8::Context> context,
968 QueryObjectPredicate* predicate,
969 std::vector<v8::Global<v8::Object>>* objects);
970
972 kSamplingNoFlags = 0,
973 kSamplingForceGC = 1 << 0,
974 kSamplingIncludeObjectsCollectedByMajorGC = 1 << 1,
975 kSamplingIncludeObjectsCollectedByMinorGC = 1 << 2,
976 };
977
984 typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate,
986 void* data);
987
997 v8::Isolate* isolate, const v8::Local<v8::Value>& v8_value,
998 uint16_t class_id, void* data);
999
1001 int GetSnapshotCount();
1002
1004 const HeapSnapshot* GetHeapSnapshot(int index);
1005
1010 SnapshotObjectId GetObjectId(Local<Value> value);
1011
1016 SnapshotObjectId GetObjectId(NativeObject value);
1017
1022 Local<Value> FindObjectById(SnapshotObjectId id);
1023
1029 void ClearObjectIds();
1030
1036 static const SnapshotObjectId kUnknownObjectId = 0;
1037
1042 public:
1047 virtual const char* GetName(Local<Object> object) = 0;
1048
1049 protected:
1050 virtual ~ObjectNameResolver() = default;
1051 };
1052
1053 enum class HeapSnapshotMode {
1057 kRegular,
1061 kExposeInternals,
1062 };
1063
1064 enum class NumericsMode {
1069 kHideNumericValues,
1073 kExposeNumericValues
1074 };
1075
1076 struct HeapSnapshotOptions final {
1077 // Manually define default constructor here to be able to use it in
1078 // `TakeSnapshot()` below.
1079 // NOLINTNEXTLINE
1081
1085 ActivityControl* control = nullptr;
1089 ObjectNameResolver* global_object_name_resolver = nullptr;
1093 HeapSnapshotMode snapshot_mode = HeapSnapshotMode::kRegular;
1097 NumericsMode numerics_mode = NumericsMode::kHideNumericValues;
1103 };
1104
1110 const HeapSnapshot* TakeHeapSnapshot(
1111 const HeapSnapshotOptions& options = HeapSnapshotOptions());
1112
1119 const HeapSnapshot* TakeHeapSnapshot(
1120 ActivityControl* control,
1121 ObjectNameResolver* global_object_name_resolver = nullptr,
1122 bool hide_internals = true, bool capture_numeric_value = false);
1123
1128 std::vector<v8::Local<v8::Value>> GetDetachedJSWrapperObjects();
1129
1139 void StartTrackingHeapObjects(bool track_allocations = false);
1140
1154 SnapshotObjectId GetHeapStats(OutputStream* stream,
1155 int64_t* timestamp_us = nullptr);
1156
1162 void StopTrackingHeapObjects();
1163
1189 bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
1190 int stack_depth = 16,
1191 SamplingFlags flags = kSamplingNoFlags);
1192
1196 void StopSamplingHeapProfiler();
1197
1204 AllocationProfile* GetAllocationProfile();
1205
1210 void DeleteAllHeapSnapshots();
1211
1212 void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
1213 void* data);
1214 void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
1215 void* data);
1216
1217 void SetGetDetachednessCallback(GetDetachednessCallback callback, void* data);
1218
1222 bool IsTakingSnapshot();
1223
1229 const char* CopyNameForHeapSnapshot(const char* name);
1230
1236 static const uint16_t kPersistentHandleNoClassId = 0;
1237
1238 private:
1243};
1244
1250 HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
1251 : index(index), count(count), size(size) { }
1252 uint32_t index; // Index of the time interval that was changed.
1253 uint32_t count; // New value of count field for the interval with this index.
1254 uint32_t size; // New value of size field for the interval with this index.
1255};
1256
1257#define CODE_EVENTS_LIST(V) \
1258 V(Builtin) \
1259 V(Callback) \
1260 V(Eval) \
1261 V(Function) \
1262 V(InterpretedFunction) \
1263 V(Handler) \
1264 V(BytecodeHandler) \
1265 V(LazyCompile) /* Unused, use kFunction instead */ \
1266 V(RegExp) \
1267 V(Script) \
1268 V(Stub) \
1269 V(Relocation)
1270
1276 kUnknownType = 0
1277#define V(Name) , k##Name##Type
1279#undef V
1281
1286 public:
1287 uintptr_t GetCodeStartAddress();
1288 size_t GetCodeSize();
1289 Local<String> GetFunctionName();
1290 Local<String> GetScriptName();
1291 int GetScriptLine();
1292 int GetScriptColumn();
1298 CodeEventType GetCodeType();
1299 const char* GetComment();
1300
1301 static const char* GetCodeEventTypeName(CodeEventType code_event_type);
1302
1303 uintptr_t GetPreviousCodeStartAddress();
1304};
1305
1310 public:
1316 explicit CodeEventHandler(Isolate* isolate);
1317 virtual ~CodeEventHandler();
1318
1327 virtual void Handle(CodeEvent* code_event) = 0;
1328
1333 void Enable();
1334
1339 void Disable();
1340
1341 private:
1346};
1347
1348} // namespace v8
1349
1350
1351#endif // V8_V8_PROFILER_H_
TFGraph * graph
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total)=0
virtual ~ActivityControl()=default
virtual const std::vector< Sample > & GetSamples()=0
virtual Node * GetRootNode()=0
virtual ~AllocationProfile()=default
CodeEventHandler(const CodeEventHandler &)
virtual void Handle(CodeEvent *code_event)=0
CodeEventHandler & operator=(const CodeEventHandler &)
CpuProfiler & operator=(const CpuProfiler &)
CpuProfiler(const CpuProfiler &)
CpuProfilingOptions & operator=(CpuProfilingOptions &&)=default
int sampling_interval_us() const
CpuProfilingMode mode_
Global< Context > filter_context_
bool has_filter_context() const
CpuProfilingMode mode() const
unsigned max_samples() const
CpuProfilingOptions(CpuProfilingOptions &&)=default
ProfilerId GetId() const
virtual ~DiscardedSamplesDelegate()=default
void SetId(ProfilerId id)
virtual Detachedness GetDetachedness()
Node & operator=(const Node &)=delete
virtual size_t SizeInBytes()=0
virtual bool IsEmbedderNode()
virtual const char * Name()=0
virtual NativeObject GetNativeObject()
virtual ~Node()=default
virtual Node * WrapperNode()
Node(const Node &)=delete
virtual const char * NamePrefix()
virtual const void * GetAddress()
virtual bool IsRootNode()
virtual void AddNativeSize(size_t size)
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::Value > &value)=0
virtual const char * GetName(Local< Object > object)=0
HeapProfiler & operator=(const HeapProfiler &)
EmbedderGraph::Node::Detachedness(*)( v8::Isolate *isolate, const v8::Local< v8::Value > &v8_value, uint16_t class_id, void *data) GetDetachednessCallback
HeapProfiler(const HeapProfiler &)
virtual ~OutputStream()=default
virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate *data, int count)
virtual WriteResult WriteAsciiChunk(char *data, int size)=0
virtual void EndOfStream()=0
virtual int GetChunkSize()
virtual bool Filter(v8::Local< v8::Object > object)=0
virtual ~QueryObjectPredicate()=default
RecordWriteMode const mode_
Isolate * isolate
TNode< Object > callback
ZoneVector< Entry > entries
EmbedderStackState
Definition common.h:15
unsigned short uint16_t
Definition unicode.cc:39
CpuProfilingStatus
void * NativeObject
Definition v8-profiler.h:30
CpuProfilingLoggingMode
@ kEagerLogging
@ kLazyLogging
CpuProfilingMode
@ kLeafNodeLineNumbers
@ kCallerLineNumbers
CpuProfilingNamingMode
@ kStandardNaming
@ kDebugNaming
uint32_t ProfilerId
Definition v8-profiler.h:32
uint32_t SnapshotObjectId
Definition v8-profiler.h:31
CodeEventType
@ kUnknownType
StateTag
Definition v8-unwinder.h:36
std::vector< Node * > children
std::vector< Allocation > allocations
Local< String > script_name
const char * deopt_reason
Definition v8-profiler.h:53
std::vector< CpuProfileDeoptFrame > stack
Definition v8-profiler.h:54
const ProfilerId id
const CpuProfilingStatus status
HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
#define V(Name)
#define CODE_EVENTS_LIST(V)
#define V8_EXPORT
Definition v8config.h:800