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

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

Issue 1625753002: Allocation sampling for paged/lo spaces (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: USE for DCHECK only variable Created 4 years, 10 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
« no previous file with comments | « src/profiler/sampling-heap-profiler.h ('k') | test/cctest/heap/test-spaces.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/profiler/sampling-heap-profiler.h" 5 #include "src/profiler/sampling-heap-profiler.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <memory> 8 #include <memory>
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/base/utils/random-number-generator.h" 10 #include "src/base/utils/random-number-generator.h"
11 #include "src/frames-inl.h" 11 #include "src/frames-inl.h"
12 #include "src/heap/heap.h" 12 #include "src/heap/heap.h"
13 #include "src/isolate.h" 13 #include "src/isolate.h"
14 #include "src/profiler/strings-storage.h" 14 #include "src/profiler/strings-storage.h"
15 15
16 namespace v8 { 16 namespace v8 {
17 namespace internal { 17 namespace internal {
18 18
19 // We sample with a Poisson process, with constant average sampling interval.
20 // This follows the exponential probability distribution with parameter
21 // λ = 1/rate where rate is the average number of bytes between samples.
22 //
23 // Let u be a uniformly distributed random number between 0 and 1, then
24 // next_sample = (- ln u) / λ
25 intptr_t SamplingAllocationObserver::GetNextSampleInterval(uint64_t rate) {
26 if (FLAG_sampling_heap_profiler_suppress_randomness) {
27 return rate;
28 }
29 double u = random_->NextDouble();
30 double next = (-std::log(u)) * rate;
31 return next < kPointerSize
32 ? kPointerSize
33 : (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));
34 }
35
19 SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names, 36 SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
20 uint64_t rate, int stack_depth) 37 uint64_t rate, int stack_depth)
21 : InlineAllocationObserver(GetNextSampleInterval( 38 : isolate_(heap->isolate()),
22 heap->isolate()->random_number_generator(), rate)),
23 isolate_(heap->isolate()),
24 heap_(heap), 39 heap_(heap),
25 random_(isolate_->random_number_generator()), 40 new_space_observer_(new SamplingAllocationObserver(
41 heap_, rate, rate, this, heap->isolate()->random_number_generator())),
42 other_spaces_observer_(new SamplingAllocationObserver(
43 heap_, rate, rate, this, heap->isolate()->random_number_generator())),
26 names_(names), 44 names_(names),
27 samples_(), 45 samples_(),
28 rate_(rate),
29 stack_depth_(stack_depth) { 46 stack_depth_(stack_depth) {
30 heap->new_space()->AddInlineAllocationObserver(this); 47 heap->new_space()->AddAllocationObserver(new_space_observer_.get());
48 AllSpaces spaces(heap);
49 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
50 if (space != heap->new_space()) {
51 space->AddAllocationObserver(other_spaces_observer_.get());
52 }
53 }
31 } 54 }
32 55
33 56
34 SamplingHeapProfiler::~SamplingHeapProfiler() { 57 SamplingHeapProfiler::~SamplingHeapProfiler() {
35 heap_->new_space()->RemoveInlineAllocationObserver(this); 58 heap_->new_space()->RemoveAllocationObserver(new_space_observer_.get());
59 AllSpaces spaces(heap_);
60 for (Space* space = spaces.next(); space != NULL; space = spaces.next()) {
61 if (space != heap_->new_space()) {
62 space->RemoveAllocationObserver(other_spaces_observer_.get());
63 }
64 }
36 65
37 // Clear samples and drop all the weak references we are keeping. 66 // Clear samples and drop all the weak references we are keeping.
38 std::set<SampledAllocation*>::iterator it; 67 std::set<SampledAllocation*>::iterator it;
39 for (it = samples_.begin(); it != samples_.end(); ++it) { 68 for (it = samples_.begin(); it != samples_.end(); ++it) {
40 delete *it; 69 delete *it;
41 } 70 }
42 std::set<SampledAllocation*> empty; 71 std::set<SampledAllocation*> empty;
43 samples_.swap(empty); 72 samples_.swap(empty);
44 } 73 }
45 74
46 void SamplingHeapProfiler::Step(int bytes_allocated, Address soon_object,
47 size_t size) {
48 DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
49 DCHECK(soon_object);
50 SampleObject(soon_object, size);
51 }
52
53 75
54 void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) { 76 void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
55 DisallowHeapAllocation no_allocation; 77 DisallowHeapAllocation no_allocation;
56 78
57 HandleScope scope(isolate_); 79 HandleScope scope(isolate_);
58 HeapObject* heap_object = HeapObject::FromAddress(soon_object); 80 HeapObject* heap_object = HeapObject::FromAddress(soon_object);
59 Handle<Object> obj(heap_object, isolate_); 81 Handle<Object> obj(heap_object, isolate_);
60 82
61 // Mark the new block as FreeSpace to make sure the heap is iterable while we 83 // Mark the new block as FreeSpace to make sure the heap is iterable while we
62 // are taking the sample. 84 // are taking the sample.
63 heap()->CreateFillerObjectAt(soon_object, static_cast<int>(size)); 85 heap()->CreateFillerObjectAt(soon_object, static_cast<int>(size));
64 86
65 Local<v8::Value> loc = v8::Utils::ToLocal(obj); 87 Local<v8::Value> loc = v8::Utils::ToLocal(obj);
66 88
67 SampledAllocation* sample = 89 SampledAllocation* sample =
68 new SampledAllocation(this, isolate_, loc, size, stack_depth_); 90 new SampledAllocation(this, isolate_, loc, size, stack_depth_);
69 samples_.insert(sample); 91 samples_.insert(sample);
70 } 92 }
71 93
72 94
73 // We sample with a Poisson process, with constant average sampling interval.
74 // This follows the exponential probability distribution with parameter
75 // λ = 1/rate where rate is the average number of bytes between samples.
76 //
77 // Let u be a uniformly distributed random number between 0 and 1, then
78 // next_sample = (- ln u) / λ
79 intptr_t SamplingHeapProfiler::GetNextSampleInterval(
80 base::RandomNumberGenerator* random, uint64_t rate) {
81 if (FLAG_sampling_heap_profiler_suppress_randomness) {
82 return rate;
83 }
84 double u = random->NextDouble();
85 double next = (-std::log(u)) * rate;
86 return next < kPointerSize
87 ? kPointerSize
88 : (next > INT_MAX ? INT_MAX : static_cast<intptr_t>(next));
89 }
90
91
92 void SamplingHeapProfiler::SampledAllocation::OnWeakCallback( 95 void SamplingHeapProfiler::SampledAllocation::OnWeakCallback(
93 const WeakCallbackInfo<SampledAllocation>& data) { 96 const WeakCallbackInfo<SampledAllocation>& data) {
94 SampledAllocation* sample = data.GetParameter(); 97 SampledAllocation* sample = data.GetParameter();
95 sample->sampling_heap_profiler_->samples_.erase(sample); 98 sample->sampling_heap_profiler_->samples_.erase(sample);
96 delete sample; 99 delete sample;
97 } 100 }
98 101
99 102
100 SamplingHeapProfiler::FunctionInfo::FunctionInfo(SharedFunctionInfo* shared, 103 SamplingHeapProfiler::FunctionInfo::FunctionInfo(SharedFunctionInfo* shared,
101 StringsStorage* names) 104 StringsStorage* names)
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 name = "(IDLE)"; 155 name = "(IDLE)";
153 break; 156 break;
154 case JS: 157 case JS:
155 name = "(JS)"; 158 name = "(JS)";
156 break; 159 break;
157 } 160 }
158 stack_.push_back(new FunctionInfo(name)); 161 stack_.push_back(new FunctionInfo(name));
159 } 162 }
160 } 163 }
161 164
162 165 v8::AllocationProfile::Node* SamplingHeapProfiler::AllocateNode(
163 SamplingHeapProfiler::Node* SamplingHeapProfiler::AllocateNode(
164 AllocationProfile* profile, const std::map<int, Script*>& scripts, 166 AllocationProfile* profile, const std::map<int, Script*>& scripts,
165 FunctionInfo* function_info) { 167 FunctionInfo* function_info) {
166 DCHECK(function_info->get_name()); 168 DCHECK(function_info->get_name());
167 DCHECK(function_info->get_script_name()); 169 DCHECK(function_info->get_script_name());
168 170
169 int line = v8::AllocationProfile::kNoLineNumberInfo; 171 int line = v8::AllocationProfile::kNoLineNumberInfo;
170 int column = v8::AllocationProfile::kNoColumnNumberInfo; 172 int column = v8::AllocationProfile::kNoColumnNumberInfo;
171 173
172 if (function_info->get_script_id() != v8::UnboundScript::kNoScriptId) { 174 if (function_info->get_script_id() != v8::UnboundScript::kNoScriptId) {
173 // Cannot use std::map<T>::at because it is not available on android. 175 // Cannot use std::map<T>::at because it is not available on android.
174 auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts); 176 auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts);
175 Handle<Script> script(non_const_scripts[function_info->get_script_id()]); 177 Handle<Script> script(non_const_scripts[function_info->get_script_id()]);
176 178
177 line = 179 line =
178 1 + Script::GetLineNumber(script, function_info->get_start_position()); 180 1 + Script::GetLineNumber(script, function_info->get_start_position());
179 column = 1 + Script::GetColumnNumber(script, 181 column = 1 + Script::GetColumnNumber(script,
180 function_info->get_start_position()); 182 function_info->get_start_position());
181 } 183 }
182 184
183 profile->nodes().push_back( 185 profile->nodes().push_back(v8::AllocationProfile::Node(
184 Node({ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String( 186 {ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(
185 function_info->get_name())), 187 function_info->get_name())),
186 ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String( 188 ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(
187 function_info->get_script_name())), 189 function_info->get_script_name())),
188 function_info->get_script_id(), function_info->get_start_position(), 190 function_info->get_script_id(), function_info->get_start_position(),
189 line, column, std::vector<Node*>(), 191 line, column, std::vector<v8::AllocationProfile::Node*>(),
190 std::vector<v8::AllocationProfile::Allocation>()})); 192 std::vector<v8::AllocationProfile::Allocation>()}));
191 193
192 return &profile->nodes().back(); 194 return &profile->nodes().back();
193 } 195 }
194 196
195 197 v8::AllocationProfile::Node* SamplingHeapProfiler::FindOrAddChildNode(
196 SamplingHeapProfiler::Node* SamplingHeapProfiler::FindOrAddChildNode(
197 AllocationProfile* profile, const std::map<int, Script*>& scripts, 198 AllocationProfile* profile, const std::map<int, Script*>& scripts,
198 Node* parent, FunctionInfo* function_info) { 199 v8::AllocationProfile::Node* parent, FunctionInfo* function_info) {
199 for (Node* child : parent->children) { 200 for (v8::AllocationProfile::Node* child : parent->children) {
200 if (child->script_id == function_info->get_script_id() && 201 if (child->script_id == function_info->get_script_id() &&
201 child->start_position == function_info->get_start_position()) 202 child->start_position == function_info->get_start_position())
202 return child; 203 return child;
203 } 204 }
204 Node* child = AllocateNode(profile, scripts, function_info); 205 v8::AllocationProfile::Node* child =
206 AllocateNode(profile, scripts, function_info);
205 parent->children.push_back(child); 207 parent->children.push_back(child);
206 return child; 208 return child;
207 } 209 }
208 210
209 211 v8::AllocationProfile::Node* SamplingHeapProfiler::AddStack(
210 SamplingHeapProfiler::Node* SamplingHeapProfiler::AddStack(
211 AllocationProfile* profile, const std::map<int, Script*>& scripts, 212 AllocationProfile* profile, const std::map<int, Script*>& scripts,
212 const std::vector<FunctionInfo*>& stack) { 213 const std::vector<FunctionInfo*>& stack) {
213 Node* node = profile->GetRootNode(); 214 v8::AllocationProfile::Node* node = profile->GetRootNode();
214 215
215 // We need to process the stack in reverse order as the top of the stack is 216 // We need to process the stack in reverse order as the top of the stack is
216 // the first element in the list. 217 // the first element in the list.
217 for (auto it = stack.rbegin(); it != stack.rend(); ++it) { 218 for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
218 FunctionInfo* function_info = *it; 219 FunctionInfo* function_info = *it;
219 node = FindOrAddChildNode(profile, scripts, node, function_info); 220 node = FindOrAddChildNode(profile, scripts, node, function_info);
220 } 221 }
221 return node; 222 return node;
222 } 223 }
223 224
(...skipping 10 matching lines...) Expand all
234 } 235 }
235 } 236 }
236 237
237 auto profile = new v8::internal::AllocationProfile(); 238 auto profile = new v8::internal::AllocationProfile();
238 239
239 // Create the root node. 240 // Create the root node.
240 FunctionInfo function_info("(root)"); 241 FunctionInfo function_info("(root)");
241 AllocateNode(profile, scripts, &function_info); 242 AllocateNode(profile, scripts, &function_info);
242 243
243 for (SampledAllocation* allocation : samples_) { 244 for (SampledAllocation* allocation : samples_) {
244 Node* node = AddStack(profile, scripts, allocation->get_stack()); 245 v8::AllocationProfile::Node* node =
246 AddStack(profile, scripts, allocation->get_stack());
245 node->allocations.push_back({allocation->get_size(), 1}); 247 node->allocations.push_back({allocation->get_size(), 1});
246 } 248 }
247 249
248 return profile; 250 return profile;
249 } 251 }
250 252
251 253
252 } // namespace internal 254 } // namespace internal
253 } // namespace v8 255 } // namespace v8
OLDNEW
« no previous file with comments | « src/profiler/sampling-heap-profiler.h ('k') | test/cctest/heap/test-spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698