V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
sampling-heap-profiler.h
1 // Copyright 2015 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_PROFILER_SAMPLING_HEAP_PROFILER_H_
6 #define V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
7 
8 #include <deque>
9 #include <map>
10 #include <memory>
11 #include <unordered_map>
12 #include "include/v8-profiler.h"
13 #include "src/heap/heap.h"
14 #include "src/profiler/strings-storage.h"
15 
16 namespace v8 {
17 
18 namespace base {
19 class RandomNumberGenerator;
20 }
21 
22 namespace internal {
23 
24 class SamplingAllocationObserver;
25 
27  public:
28  AllocationProfile() = default;
29 
31  return nodes_.size() == 0 ? nullptr : &nodes_.front();
32  }
33 
34  const std::vector<v8::AllocationProfile::Sample>& GetSamples() override {
35  return samples_;
36  }
37 
38  private:
39  std::deque<v8::AllocationProfile::Node> nodes_;
40  std::vector<v8::AllocationProfile::Sample> samples_;
41 
42  friend class SamplingHeapProfiler;
43 
44  DISALLOW_COPY_AND_ASSIGN(AllocationProfile);
45 };
46 
48  public:
50  public:
51  typedef uint64_t FunctionId;
52  AllocationNode(AllocationNode* parent, const char* name, int script_id,
53  int start_position, uint32_t id)
54  : parent_(parent),
55  script_id_(script_id),
56  script_position_(start_position),
57  name_(name),
58  id_(id) {}
59 
60  AllocationNode* FindChildNode(FunctionId id) {
61  auto it = children_.find(id);
62  return it != children_.end() ? it->second.get() : nullptr;
63  }
64 
65  AllocationNode* AddChildNode(FunctionId id,
66  std::unique_ptr<AllocationNode> node) {
67  return children_.emplace(id, std::move(node)).first->second.get();
68  }
69 
70  static FunctionId function_id(int script_id, int start_position,
71  const char* name) {
72  // script_id == kNoScriptId case:
73  // Use function name pointer as an id. Names derived from VM state
74  // must not collide with the builtin names. The least significant bit
75  // of the id is set to 1.
76  if (script_id == v8::UnboundScript::kNoScriptId) {
77  return reinterpret_cast<intptr_t>(name) | 1;
78  }
79  // script_id != kNoScriptId case:
80  // Use script_id, start_position pair to uniquelly identify the node.
81  // The least significant bit of the id is set to 0.
82  DCHECK(static_cast<unsigned>(start_position) < (1u << 31));
83  return (static_cast<uint64_t>(script_id) << 32) + (start_position << 1);
84  }
85 
86  private:
87  // TODO(alph): make use of unordered_map's here. Pay attention to
88  // iterator invalidation during TranslateAllocationNode.
89  std::map<size_t, unsigned int> allocations_;
90  std::map<FunctionId, std::unique_ptr<AllocationNode>> children_;
91  AllocationNode* const parent_;
92  const int script_id_;
93  const int script_position_;
94  const char* const name_;
95  uint32_t id_;
96  bool pinned_ = false;
97 
98  friend class SamplingHeapProfiler;
99 
100  DISALLOW_COPY_AND_ASSIGN(AllocationNode);
101  };
102 
103  struct Sample {
104  Sample(size_t size_, AllocationNode* owner_, Local<Value> local_,
105  SamplingHeapProfiler* profiler_, uint64_t sample_id)
106  : size(size_),
107  owner(owner_),
108  global(Global<Value>(
109  reinterpret_cast<v8::Isolate*>(profiler_->isolate_), local_)),
110  profiler(profiler_),
111  sample_id(sample_id) {}
112  ~Sample() { global.Reset(); }
113  const size_t size;
114  AllocationNode* const owner;
115  Global<Value> global;
116  SamplingHeapProfiler* const profiler;
117  const uint64_t sample_id;
118 
119  private:
120  DISALLOW_COPY_AND_ASSIGN(Sample);
121  };
122 
123  SamplingHeapProfiler(Heap* heap, StringsStorage* names, uint64_t rate,
124  int stack_depth, v8::HeapProfiler::SamplingFlags flags);
126 
127  v8::AllocationProfile* GetAllocationProfile();
128  StringsStorage* names() const { return names_; }
129 
130  private:
131  void SampleObject(Address soon_object, size_t size);
132 
133  const std::vector<v8::AllocationProfile::Sample> BuildSamples() const;
134 
135  AllocationNode* FindOrAddChildNode(AllocationNode* parent, const char* name,
136  int script_id, int start_position);
137  static void OnWeakCallback(const WeakCallbackInfo<Sample>& data);
138 
139  uint32_t next_node_id() { return ++last_node_id_; }
140  uint64_t next_sample_id() { return ++last_sample_id_; }
141 
142  // Methods that construct v8::AllocationProfile.
143 
144  // Translates the provided AllocationNode *node* returning an equivalent
145  // AllocationProfile::Node. The newly created AllocationProfile::Node is added
146  // to the provided AllocationProfile *profile*. Line numbers, column numbers,
147  // and script names are resolved using *scripts* which maps all currently
148  // loaded scripts keyed by their script id.
149  v8::AllocationProfile::Node* TranslateAllocationNode(
150  AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
151  const std::map<int, Handle<Script>>& scripts);
152  v8::AllocationProfile::Allocation ScaleSample(size_t size,
153  unsigned int count) const;
154  AllocationNode* AddStack();
155 
156  Isolate* const isolate_;
157  Heap* const heap_;
158  uint64_t last_sample_id_ = 0;
159  uint32_t last_node_id_ = 0;
160  std::unique_ptr<SamplingAllocationObserver> new_space_observer_;
161  std::unique_ptr<SamplingAllocationObserver> other_spaces_observer_;
162  StringsStorage* const names_;
163  AllocationNode profile_root_;
164  std::unordered_map<Sample*, std::unique_ptr<Sample>> samples_;
165  const int stack_depth_;
166  const uint64_t rate_;
167  v8::HeapProfiler::SamplingFlags flags_;
168 
169  friend class SamplingAllocationObserver;
170 
171  DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler);
172 };
173 
175  public:
176  SamplingAllocationObserver(Heap* heap, intptr_t step_size, uint64_t rate,
177  SamplingHeapProfiler* profiler,
179  : AllocationObserver(step_size),
180  profiler_(profiler),
181  heap_(heap),
182  random_(random),
183  rate_(rate) {}
184  ~SamplingAllocationObserver() override = default;
185 
186  protected:
187  void Step(int bytes_allocated, Address soon_object, size_t size) override {
188  USE(heap_);
189  DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
190  if (soon_object) {
191  // TODO(ofrobots): it would be better to sample the next object rather
192  // than skipping this sample epoch if soon_object happens to be null.
193  profiler_->SampleObject(soon_object, size);
194  }
195  }
196 
197  intptr_t GetNextStepSize() override { return GetNextSampleInterval(rate_); }
198 
199  private:
200  intptr_t GetNextSampleInterval(uint64_t rate);
201  SamplingHeapProfiler* const profiler_;
202  Heap* const heap_;
203  base::RandomNumberGenerator* const random_;
204  uint64_t const rate_;
205 };
206 
207 } // namespace internal
208 } // namespace v8
209 
210 #endif // V8_PROFILER_SAMPLING_HEAP_PROFILER_H_
Definition: v8.h:94
Definition: v8.h:85
v8::AllocationProfile::Node * GetRootNode() override
Definition: libplatform.h:13