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

Side by Side Diff: src/cpu-profiler.cc

Issue 2438002: CPU profiler: sample call stack on profiling start. (Closed)
Patch Set: Created 10 years, 6 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/cpu-profiler.h ('k') | src/profile-generator.h » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "cpu-profiler-inl.h" 30 #include "cpu-profiler-inl.h"
31 31
32 #ifdef ENABLE_LOGGING_AND_PROFILING 32 #ifdef ENABLE_LOGGING_AND_PROFILING
33 33
34 #include "frames-inl.h"
34 #include "log-inl.h" 35 #include "log-inl.h"
35 36
36 #include "../include/v8-profiler.h" 37 #include "../include/v8-profiler.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
40 41
41 static const int kEventsBufferSize = 256*KB; 42 static const int kEventsBufferSize = 256*KB;
42 static const int kTickSamplesBufferChunkSize = 64*KB; 43 static const int kTickSamplesBufferChunkSize = 64*KB;
43 static const int kTickSamplesBufferChunksCount = 16; 44 static const int kTickSamplesBufferChunksCount = 16;
44 45
45 46
46 ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator) 47 ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
47 : generator_(generator), 48 : generator_(generator),
48 running_(false), 49 running_(false),
49 ticks_buffer_(sizeof(TickSampleEventRecord), 50 ticks_buffer_(sizeof(TickSampleEventRecord),
50 kTickSamplesBufferChunkSize, 51 kTickSamplesBufferChunkSize,
51 kTickSamplesBufferChunksCount), 52 kTickSamplesBufferChunksCount),
52 enqueue_order_(0) { } 53 enqueue_order_(0) {
54 }
53 55
54 56
55 void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag, 57 void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
56 const char* prefix, 58 const char* prefix,
57 String* name, 59 String* name,
58 Address start) { 60 Address start) {
59 if (FilterOutCodeCreateEvent(tag)) return; 61 if (FilterOutCodeCreateEvent(tag)) return;
60 CodeEventsContainer evt_rec; 62 CodeEventsContainer evt_rec;
61 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; 63 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
62 rec->type = CodeEventRecord::CODE_CREATION; 64 rec->type = CodeEventRecord::CODE_CREATION;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; 176 CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
175 rec->type = CodeEventRecord::CODE_CREATION; 177 rec->type = CodeEventRecord::CODE_CREATION;
176 rec->order = ++enqueue_order_; 178 rec->order = ++enqueue_order_;
177 rec->start = start; 179 rec->start = start;
178 rec->entry = generator_->NewCodeEntry(tag, prefix, name); 180 rec->entry = generator_->NewCodeEntry(tag, prefix, name);
179 rec->size = size; 181 rec->size = size;
180 events_buffer_.Enqueue(evt_rec); 182 events_buffer_.Enqueue(evt_rec);
181 } 183 }
182 184
183 185
186 void ProfilerEventsProcessor::AddCurrentStack() {
187 TickSampleEventRecord record;
188 TickSample* sample = &record.sample;
189 sample->state = VMState::current_state();
190 sample->pc = reinterpret_cast<Address>(sample); // Not NULL.
191 sample->frames_count = 0;
192 for (StackTraceFrameIterator it;
193 !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
194 it.Advance()) {
195 JavaScriptFrame* frame = it.frame();
196 sample->stack[sample->frames_count++] =
197 reinterpret_cast<Address>(frame->function());
198 }
199 record.order = enqueue_order_;
200 ticks_from_vm_buffer_.Enqueue(record);
201 }
202
203
184 bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) { 204 bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
185 if (!events_buffer_.IsEmpty()) { 205 if (!events_buffer_.IsEmpty()) {
186 CodeEventsContainer record; 206 CodeEventsContainer record;
187 events_buffer_.Dequeue(&record); 207 events_buffer_.Dequeue(&record);
188 switch (record.generic.type) { 208 switch (record.generic.type) {
189 #define PROFILER_TYPE_CASE(type, clss) \ 209 #define PROFILER_TYPE_CASE(type, clss) \
190 case CodeEventRecord::type: \ 210 case CodeEventRecord::type: \
191 record.clss##_.UpdateCodeMap(generator_->code_map()); \ 211 record.clss##_.UpdateCodeMap(generator_->code_map()); \
192 break; 212 break;
193 213
194 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE) 214 CODE_EVENTS_TYPE_LIST(PROFILER_TYPE_CASE)
195 215
196 #undef PROFILER_TYPE_CASE 216 #undef PROFILER_TYPE_CASE
197 default: return true; // Skip record. 217 default: return true; // Skip record.
198 } 218 }
199 *dequeue_order = record.generic.order; 219 *dequeue_order = record.generic.order;
200 return true; 220 return true;
201 } 221 }
202 return false; 222 return false;
203 } 223 }
204 224
205 225
206 bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) { 226 bool ProfilerEventsProcessor::ProcessTicks(unsigned dequeue_order) {
207 while (true) { 227 while (true) {
228 if (!ticks_from_vm_buffer_.IsEmpty()
229 && ticks_from_vm_buffer_.Peek()->order == dequeue_order) {
230 TickSampleEventRecord record;
231 ticks_from_vm_buffer_.Dequeue(&record);
232 generator_->RecordTickSample(record.sample);
233 }
234
208 const TickSampleEventRecord* rec = 235 const TickSampleEventRecord* rec =
209 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue()); 236 TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
210 if (rec == NULL) return false; 237 if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
211 if (rec->order == dequeue_order) { 238 if (rec->order == dequeue_order) {
212 generator_->RecordTickSample(rec->sample); 239 generator_->RecordTickSample(rec->sample);
213 ticks_buffer_.FinishDequeue(); 240 ticks_buffer_.FinishDequeue();
214 } else { 241 } else {
215 return true; 242 return true;
216 } 243 }
217 } 244 }
218 } 245 }
219 246
220 247
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 CpuProfiler::~CpuProfiler() { 436 CpuProfiler::~CpuProfiler() {
410 delete token_enumerator_; 437 delete token_enumerator_;
411 delete profiles_; 438 delete profiles_;
412 } 439 }
413 440
414 441
415 void CpuProfiler::StartCollectingProfile(const char* title) { 442 void CpuProfiler::StartCollectingProfile(const char* title) {
416 if (profiles_->StartProfiling(title, next_profile_uid_++)) { 443 if (profiles_->StartProfiling(title, next_profile_uid_++)) {
417 StartProcessorIfNotStarted(); 444 StartProcessorIfNotStarted();
418 } 445 }
446 processor_->AddCurrentStack();
419 } 447 }
420 448
421 449
422 void CpuProfiler::StartCollectingProfile(String* title) { 450 void CpuProfiler::StartCollectingProfile(String* title) {
423 if (profiles_->StartProfiling(title, next_profile_uid_++)) { 451 StartCollectingProfile(profiles_->GetName(title));
424 StartProcessorIfNotStarted();
425 }
426 } 452 }
427 453
428 454
429 void CpuProfiler::StartProcessorIfNotStarted() { 455 void CpuProfiler::StartProcessorIfNotStarted() {
430 if (processor_ == NULL) { 456 if (processor_ == NULL) {
431 // Disable logging when using the new implementation. 457 // Disable logging when using the new implementation.
432 saved_logging_nesting_ = Logger::logging_nesting_; 458 saved_logging_nesting_ = Logger::logging_nesting_;
433 Logger::logging_nesting_ = 0; 459 Logger::logging_nesting_ = 0;
434 generator_ = new ProfileGenerator(profiles_); 460 generator_ = new ProfileGenerator(profiles_);
435 processor_ = new ProfilerEventsProcessor(generator_); 461 processor_ = new ProfilerEventsProcessor(generator_);
436 processor_->Start(); 462 processor_->Start();
437 // Enable stack sampling.
438 // It is important to have it started prior to logging, see issue 683:
439 // http://code.google.com/p/v8/issues/detail?id=683
440 reinterpret_cast<Sampler*>(Logger::ticker_)->Start();
441 // Enumerate stuff we already have in the heap. 463 // Enumerate stuff we already have in the heap.
442 if (Heap::HasBeenSetup()) { 464 if (Heap::HasBeenSetup()) {
443 Logger::LogCodeObjects(); 465 Logger::LogCodeObjects();
444 Logger::LogCompiledFunctions(); 466 Logger::LogCompiledFunctions();
445 Logger::LogFunctionObjects(); 467 Logger::LogFunctionObjects();
446 Logger::LogAccessorCallbacks(); 468 Logger::LogAccessorCallbacks();
447 } 469 }
470 // Enable stack sampling.
471 reinterpret_cast<Sampler*>(Logger::ticker_)->Start();
448 } 472 }
449 } 473 }
450 474
451 475
452 CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) { 476 CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
453 const double actual_sampling_rate = generator_->actual_sampling_rate(); 477 const double actual_sampling_rate = generator_->actual_sampling_rate();
454 StopProcessorIfLastProfile(); 478 StopProcessorIfLastProfile();
455 CpuProfile* result = profiles_->StopProfiling(CodeEntry::kNoSecurityToken, 479 CpuProfile* result = profiles_->StopProfiling(CodeEntry::kNoSecurityToken,
456 title, 480 title,
457 actual_sampling_rate); 481 actual_sampling_rate);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 void CpuProfiler::TearDown() { 527 void CpuProfiler::TearDown() {
504 #ifdef ENABLE_LOGGING_AND_PROFILING 528 #ifdef ENABLE_LOGGING_AND_PROFILING
505 if (singleton_ != NULL) { 529 if (singleton_ != NULL) {
506 delete singleton_; 530 delete singleton_;
507 } 531 }
508 singleton_ = NULL; 532 singleton_ = NULL;
509 #endif 533 #endif
510 } 534 }
511 535
512 } } // namespace v8::internal 536 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/cpu-profiler.h ('k') | src/profile-generator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698