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

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

Issue 1967673002: Sampling heap profiler: use map instead of vector for children. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addressing comments. Created 4 years, 7 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') | no next file » | 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"
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 const WeakCallbackInfo<Sample>& data) { 118 const WeakCallbackInfo<Sample>& data) {
119 Sample* sample = data.GetParameter(); 119 Sample* sample = data.GetParameter();
120 AllocationNode* node = sample->owner; 120 AllocationNode* node = sample->owner;
121 DCHECK(node->allocations_[sample->size] > 0); 121 DCHECK(node->allocations_[sample->size] > 0);
122 node->allocations_[sample->size]--; 122 node->allocations_[sample->size]--;
123 if (node->allocations_[sample->size] == 0) { 123 if (node->allocations_[sample->size] == 0) {
124 node->allocations_.erase(sample->size); 124 node->allocations_.erase(sample->size);
125 while (node->allocations_.empty() && node->children_.empty() && 125 while (node->allocations_.empty() && node->children_.empty() &&
126 node->parent_ && !node->parent_->pinned_) { 126 node->parent_ && !node->parent_->pinned_) {
127 AllocationNode* parent = node->parent_; 127 AllocationNode* parent = node->parent_;
128 parent->children_.erase( 128 AllocationNode::FunctionId id = AllocationNode::function_id(
129 std::find(parent->children_.begin(), parent->children_.end(), node)); 129 node->script_id_, node->script_position_, node->name_);
130 parent->children_.erase(id);
130 delete node; 131 delete node;
131 node = parent; 132 node = parent;
132 } 133 }
133 } 134 }
134 sample->profiler->samples_.erase(sample); 135 sample->profiler->samples_.erase(sample);
135 delete sample; 136 delete sample;
136 } 137 }
137 138
138 SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode( 139 SamplingHeapProfiler::AllocationNode*
139 AllocationNode* parent, const char* name, int script_id, 140 SamplingHeapProfiler::AllocationNode::FindOrAddChildNode(const char* name,
140 int start_position) { 141 int script_id,
141 for (AllocationNode* child : parent->children_) { 142 int start_position) {
142 if (child->script_id_ == script_id && 143 FunctionId id = function_id(script_id, start_position, name);
143 child->script_position_ == start_position && 144 auto it = children_.find(id);
144 strcmp(child->name_, name) == 0) { 145 if (it != children_.end()) {
145 return child; 146 DCHECK(strcmp(it->second->name_, name) == 0);
146 } 147 return it->second;
147 } 148 }
148 AllocationNode* child = 149 auto child = new AllocationNode(this, name, script_id, start_position);
149 new AllocationNode(parent, name, script_id, start_position); 150 children_.insert(std::make_pair(id, child));
150 parent->children_.push_back(child);
151 return child; 151 return child;
152 } 152 }
153 153
154 SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { 154 SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
155 AllocationNode* node = &profile_root_; 155 AllocationNode* node = &profile_root_;
156 156
157 std::vector<SharedFunctionInfo*> stack; 157 std::vector<SharedFunctionInfo*> stack;
158 JavaScriptFrameIterator it(isolate_); 158 JavaScriptFrameIterator it(isolate_);
159 int frames_captured = 0; 159 int frames_captured = 0;
160 while (!it.done() && frames_captured < stack_depth_) { 160 while (!it.done() && frames_captured < stack_depth_) {
(...skipping 20 matching lines...) Expand all
181 case EXTERNAL: 181 case EXTERNAL:
182 name = "(EXTERNAL)"; 182 name = "(EXTERNAL)";
183 break; 183 break;
184 case IDLE: 184 case IDLE:
185 name = "(IDLE)"; 185 name = "(IDLE)";
186 break; 186 break;
187 case JS: 187 case JS:
188 name = "(JS)"; 188 name = "(JS)";
189 break; 189 break;
190 } 190 }
191 return FindOrAddChildNode(node, name, v8::UnboundScript::kNoScriptId, 0); 191 return node->FindOrAddChildNode(name, v8::UnboundScript::kNoScriptId, 0);
192 } 192 }
193 193
194 // We need to process the stack in reverse order as the top of the stack is 194 // We need to process the stack in reverse order as the top of the stack is
195 // the first element in the list. 195 // the first element in the list.
196 for (auto it = stack.rbegin(); it != stack.rend(); ++it) { 196 for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
197 SharedFunctionInfo* shared = *it; 197 SharedFunctionInfo* shared = *it;
198 const char* name = this->names()->GetFunctionName(shared->DebugName()); 198 const char* name = this->names()->GetFunctionName(shared->DebugName());
199 int script_id = v8::UnboundScript::kNoScriptId; 199 int script_id = v8::UnboundScript::kNoScriptId;
200 if (shared->script()->IsScript()) { 200 if (shared->script()->IsScript()) {
201 Script* script = Script::cast(shared->script()); 201 Script* script = Script::cast(shared->script());
202 script_id = script->id(); 202 script_id = script->id();
203 } 203 }
204 node = FindOrAddChildNode(node, name, script_id, shared->start_position()); 204 node = node->FindOrAddChildNode(name, script_id, shared->start_position());
205 } 205 }
206 return node; 206 return node;
207 } 207 }
208 208
209 v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode( 209 v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode(
210 AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node, 210 AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node,
211 const std::map<int, Handle<Script>>& scripts) { 211 const std::map<int, Handle<Script>>& scripts) {
212 // By pinning the node we make sure its children won't get disposed if 212 // By pinning the node we make sure its children won't get disposed if
213 // a GC kicks in during the tree retrieval. 213 // a GC kicks in during the tree retrieval.
214 node->pinned_ = true; 214 node->pinned_ = true;
(...skipping 22 matching lines...) Expand all
237 for (auto alloc : node->allocations_) { 237 for (auto alloc : node->allocations_) {
238 allocations.push_back(ScaleSample(alloc.first, alloc.second)); 238 allocations.push_back(ScaleSample(alloc.first, alloc.second));
239 } 239 }
240 240
241 profile->nodes().push_back(v8::AllocationProfile::Node( 241 profile->nodes().push_back(v8::AllocationProfile::Node(
242 {ToApiHandle<v8::String>( 242 {ToApiHandle<v8::String>(
243 isolate_->factory()->InternalizeUtf8String(node->name_)), 243 isolate_->factory()->InternalizeUtf8String(node->name_)),
244 script_name, node->script_id_, node->script_position_, line, column, 244 script_name, node->script_id_, node->script_position_, line, column,
245 std::vector<v8::AllocationProfile::Node*>(), allocations})); 245 std::vector<v8::AllocationProfile::Node*>(), allocations}));
246 v8::AllocationProfile::Node* current = &profile->nodes().back(); 246 v8::AllocationProfile::Node* current = &profile->nodes().back();
247 size_t child_len = node->children_.size(); 247 // The children map may have nodes inserted into it during translation
248 // The children vector may have nodes appended to it during translation
249 // because the translation may allocate strings on the JS heap that have 248 // because the translation may allocate strings on the JS heap that have
250 // the potential to be sampled. We cache the length of the vector before 249 // the potential to be sampled. That's ok since map iterators are not
251 // iteration so that nodes appended to the vector during iteration are 250 // invalidated upon std::map insertion.
252 // not processed. 251 for (auto it : node->children_) {
253 for (size_t i = 0; i < child_len; i++) {
254 current->children.push_back( 252 current->children.push_back(
255 TranslateAllocationNode(profile, node->children_[i], scripts)); 253 TranslateAllocationNode(profile, it.second, scripts));
256 } 254 }
257 node->pinned_ = false; 255 node->pinned_ = false;
258 return current; 256 return current;
259 } 257 }
260 258
261 v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() { 259 v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() {
262 if (flags_ & v8::HeapProfiler::kSamplingForceGC) { 260 if (flags_ & v8::HeapProfiler::kSamplingForceGC) {
263 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, 261 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
264 "SamplingHeapProfiler"); 262 "SamplingHeapProfiler");
265 } 263 }
266 // To resolve positions to line/column numbers, we will need to look up 264 // To resolve positions to line/column numbers, we will need to look up
267 // scripts. Build a map to allow fast mapping from script id to script. 265 // scripts. Build a map to allow fast mapping from script id to script.
268 std::map<int, Handle<Script>> scripts; 266 std::map<int, Handle<Script>> scripts;
269 { 267 {
270 Script::Iterator iterator(isolate_); 268 Script::Iterator iterator(isolate_);
271 while (Script* script = iterator.Next()) { 269 while (Script* script = iterator.Next()) {
272 scripts[script->id()] = handle(script); 270 scripts[script->id()] = handle(script);
273 } 271 }
274 } 272 }
275 auto profile = new v8::internal::AllocationProfile(); 273 auto profile = new v8::internal::AllocationProfile();
276 TranslateAllocationNode(profile, &profile_root_, scripts); 274 TranslateAllocationNode(profile, &profile_root_, scripts);
277 return profile; 275 return profile;
278 } 276 }
279 277
280 278
281 } // namespace internal 279 } // namespace internal
282 } // namespace v8 280 } // namespace v8
OLDNEW
« no previous file with comments | « src/profiler/sampling-heap-profiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698