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

Side by Side Diff: src/profiler/sampling-heap-profiler.cc

Issue 1555553002: [profiler] Implement POC Sampling Heap Profiler (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: cleanup samples when sampling heap profiler is stopped Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "src/api.h"
6 #include "src/frames-inl.h"
7 #include "src/heap/heap.h"
8 #include "src/isolate.h"
9 #include "src/profiler/sampling-heap-profiler.h"
10 #include "src/profiler/strings-storage.h"
11
12 namespace v8 {
13 namespace internal {
14
15 SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
16 uint64_t rate, int stack_depth)
17 : InlineAllocationObserver(GetNextSampleInterval(
18 heap->isolate()->random_number_generator(), rate)),
19 isolate_(heap->isolate()),
20 heap_(heap),
21 random_(isolate_->random_number_generator()),
22 names_(names),
23 samples_(),
24 rate_(rate),
25 stack_depth_(stack_depth) {
26 heap->new_space()->AddInlineAllocationObserver(this);
27 }
28
29
30 SamplingHeapProfiler::~SamplingHeapProfiler() {
31 heap_->new_space()->RemoveInlineAllocationObserver(this);
32
33 // Clear samples and drop all the weak references we are keeping.
34 std::set<SampledAllocation*>::iterator it;
35 for (it = samples_.begin(); it != samples_.end(); ++it) {
36 delete *it;
37 }
38 std::set<SampledAllocation*> empty{};
39 samples_.swap(empty);
40 }
41
42 void SamplingHeapProfiler::Step(int bytes_allocated, Address soon_object,
43 size_t size) {
44 DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
45 DCHECK(soon_object);
46 SampleObject(soon_object, size);
47 }
48
49
50 void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
51 DisallowHeapAllocation no_allocation;
52
53 HandleScope scope(isolate_);
54 HeapObject* heap_object = HeapObject::FromAddress(soon_object);
55 Handle<Object> obj(heap_object, isolate_);
56
57 // Mark the new block as FreeSpace to make sure the heap is iterable while we
58 // are taking the sample.
59 heap()->CreateFillerObjectAt(soon_object, static_cast<int>(size));
60
61 Local<v8::Value> loc = v8::Utils::ToLocal(obj);
62
63 SampledAllocation* sample =
64 new SampledAllocation(this, isolate_, loc, size, stack_depth_);
65 samples_.insert(sample);
66 }
67
68
69 // We sample with a Poisson process, with constant average sampling interval.
70 // This follows the exponential probability distribution with parameter
71 // λ = 1/rate where rate is the average number of bytes between samples.
72 //
73 // Let u be a uniformly distributed random number between 0 and 1, then
74 // next_sample = (- ln u) / λ
75 intptr_t SamplingHeapProfiler::GetNextSampleInterval(
76 base::RandomNumberGenerator* random, uint64_t rate) {
77 double u = random->NextDouble();
78 double next = (-std::log(u)) * rate;
79 return std::max(static_cast<intptr_t>(kPointerSize),
80 static_cast<intptr_t>(next));
81 }
82
83
84 void SamplingHeapProfiler::GetHeapSample(OutputStream* stream) {
85 std::map<int, Script*> scripts;
86 {
87 Script::Iterator iterator(isolate_);
88 Script* script;
89 while ((script = iterator.Next())) {
90 scripts[script->id()] = script;
91 }
92 }
93
94 OutputStreamWriter writer(stream);
95 writer.AddString("[\n");
96 std::set<SampledAllocation*>::iterator it;
97 for (it = samples_.begin(); it != samples_.end(); ++it) {
98 auto sample = *it;
99 if (it != samples_.begin()) {
100 writer.AddString(",");
101 }
102 writer.AddString(" {\"size\": ");
103 writer.AddNumber(static_cast<unsigned>(sample->get_size()));
104 writer.AddString(", \"stack\": [\n");
105 List<FunctionInfo*>& stack = sample->get_stack();
106 for (int i = 0; i < stack.length(); ++i) {
107 FunctionInfo* info = stack[i];
108 int line = -1;
109 int column = -1;
110 if (info->script_id != -1) {
111 Handle<Script> script(scripts[info->script_id]);
112 line = Script::GetLineNumber(script, info->start_position);
113 column = Script::GetColumnNumber(script, info->start_position);
114 }
115
116 writer.AddString("\t{\"name\": \"");
117 writer.AddString(info->name);
118 writer.AddString("\"");
119 if (line != -1) {
120 DCHECK(column != -1);
121 writer.AddString(", \"line\": ");
122 writer.AddNumber(line);
123 writer.AddString(", \"column\": ");
124 writer.AddNumber(column);
125 }
126 writer.AddString(", \"scriptName\": \"");
127 writer.AddString(info->script_name);
128 if (i < (stack.length() - 1)) {
129 writer.AddString("\"},\n");
130 } else {
131 writer.AddString("\"}\n");
132 }
133 }
134 writer.AddString(" ]}\n");
135 }
136 writer.AddString("]\n");
137 writer.Finalize();
138 }
139
140 void SamplingHeapProfiler::SampledAllocation::OnWeakCallback(
141 const WeakCallbackInfo<SampledAllocation>& data) {
142 SampledAllocation* sample = data.GetParameter();
143 sample->shp_->samples_.erase(sample);
144 delete sample;
145 }
146
147
148 SamplingHeapProfiler::FunctionInfo::FunctionInfo(SharedFunctionInfo* shared,
149 StringsStorage* names)
150 : name(names->GetFunctionName(shared->DebugName())),
151 script_name(""),
152 script_id(-1),
153 start_position(-1) {
154 if (shared->script()->IsScript()) {
155 Script* script = Script::cast(shared->script());
156 script_id = script->id();
157 start_position = shared->start_position();
158 if (script->name()->IsName()) {
159 Name* name = Name::cast(script->name());
160 script_name = names->GetName(name);
161 }
162 }
163 }
164
165 SamplingHeapProfiler::SampledAllocation::SampledAllocation(
166 SamplingHeapProfiler* shp, Isolate* isolate, Local<Value> local,
167 size_t size, int max_frames)
168 : shp_(shp),
169 global_(reinterpret_cast<v8::Isolate*>(isolate), local),
170 size_(size) {
171 global_.SetWeak(this, OnWeakCallback, WeakCallbackType::kParameter);
172
173
174 StackTraceFrameIterator it(isolate);
175 int frames_captured = 0;
176 while (!it.done() && frames_captured < max_frames) {
177 JavaScriptFrame* frame = it.frame();
178 SharedFunctionInfo* shared = frame->function()->shared();
179 stack_.Add(new FunctionInfo(shared, shp->names()));
180
181 frames_captured++;
182 it.Advance();
183 }
184 }
185
186
187 } // namespace internal
188 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698