| Index: src/cpu-profiler.cc
|
| diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
|
| index 747542f73781d79efc5ec5d297af6d7b6c1020da..f8698b31005ce1953c9dd2bb2340e7f5354652e1 100644
|
| --- a/src/cpu-profiler.cc
|
| +++ b/src/cpu-profiler.cc
|
| @@ -40,18 +40,18 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -static const int kTickSamplesBufferChunkSize = 64 * KB;
|
| -static const int kTickSamplesBufferChunksCount = 16;
|
| static const int kProfilerStackSize = 64 * KB;
|
|
|
|
|
| -ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
|
| +ProfilerEventsProcessor::ProfilerEventsProcessor(
|
| + ProfileGenerator* generator,
|
| + Sampler* sampler,
|
| + int period_in_useconds)
|
| : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
|
| generator_(generator),
|
| + sampler_(sampler),
|
| running_(true),
|
| - ticks_buffer_(sizeof(TickSampleEventRecord),
|
| - kTickSamplesBufferChunkSize,
|
| - kTickSamplesBufferChunksCount),
|
| + period_in_useconds_(period_in_useconds),
|
| last_code_event_id_(0), last_processed_code_event_id_(0) {
|
| }
|
|
|
| @@ -114,41 +114,51 @@ bool ProfilerEventsProcessor::ProcessTicks() {
|
| generator_->RecordTickSample(record.sample);
|
| }
|
|
|
| - const TickSampleEventRecord* rec =
|
| - TickSampleEventRecord::cast(ticks_buffer_.StartDequeue());
|
| - if (rec == NULL) return !ticks_from_vm_buffer_.IsEmpty();
|
| - // Make a local copy of tick sample record to ensure that it won't
|
| - // be modified as we are processing it. This is possible as the
|
| - // sampler writes w/o any sync to the queue, so if the processor
|
| - // will get far behind, a record may be modified right under its
|
| - // feet.
|
| - TickSampleEventRecord record = *rec;
|
| - if (record.order != last_processed_code_event_id_) return true;
|
| -
|
| - // A paranoid check to make sure that we don't get a memory overrun
|
| - // in case of frames_count having a wild value.
|
| - if (record.sample.frames_count < 0
|
| - || record.sample.frames_count > TickSample::kMaxFramesCount)
|
| - record.sample.frames_count = 0;
|
| - generator_->RecordTickSample(record.sample);
|
| + const TickSampleEventRecord* record = ticks_buffer_.StartDequeue();
|
| + if (record == NULL) return !ticks_from_vm_buffer_.IsEmpty();
|
| + if (record->order != last_processed_code_event_id_) return true;
|
| + generator_->RecordTickSample(record->sample);
|
| ticks_buffer_.FinishDequeue();
|
| }
|
| }
|
|
|
|
|
| -void ProfilerEventsProcessor::Run() {
|
| - while (running_) {
|
| - // Process ticks until we have any.
|
| +void ProfilerEventsProcessor::ProcessEventsAndDoSample() {
|
| + int64_t stop_time = OS::Ticks() + period_in_useconds_;
|
| + // Keep processing existing events until we need to do next sample.
|
| + while (OS::Ticks() < stop_time) {
|
| if (ProcessTicks()) {
|
| - // All ticks of the current last_processed_code_event_id_ are processed,
|
| + // All ticks of the current dequeue_order are processed,
|
| // proceed to the next code event.
|
| ProcessCodeEvent();
|
| }
|
| - YieldCPU();
|
| + }
|
| + // Schedule next sample. sampler_ is NULL in tests.
|
| + if (sampler_) sampler_->DoSample();
|
| +}
|
| +
|
| +
|
| +void ProfilerEventsProcessor::ProcessEventsAndYield() {
|
| + // Process ticks until we have any.
|
| + if (ProcessTicks()) {
|
| + // All ticks of the current dequeue_order are processed,
|
| + // proceed to the next code event.
|
| + ProcessCodeEvent();
|
| + }
|
| + YieldCPU();
|
| +}
|
| +
|
| +
|
| +void ProfilerEventsProcessor::Run() {
|
| + while (running_) {
|
| + if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
|
| + ProcessEventsAndDoSample();
|
| + } else {
|
| + ProcessEventsAndYield();
|
| + }
|
| }
|
|
|
| // Process remaining tick events.
|
| - ticks_buffer_.FlushResidualRecords();
|
| do {
|
| ProcessTicks();
|
| } while (ProcessCodeEvent());
|
| @@ -166,12 +176,6 @@ CpuProfile* CpuProfiler::GetProfile(int index) {
|
| }
|
|
|
|
|
| -TickSample* CpuProfiler::TickSampleEvent() {
|
| - if (is_profiling_) return processor_->TickSampleEvent();
|
| - return NULL;
|
| -}
|
| -
|
| -
|
| void CpuProfiler::DeleteAllProfiles() {
|
| if (is_profiling_) StopProcessor();
|
| ResetProfiles();
|
| @@ -428,9 +432,10 @@ void CpuProfiler::StartProcessorIfNotStarted() {
|
| saved_logging_nesting_ = logger->logging_nesting_;
|
| logger->logging_nesting_ = 0;
|
| generator_ = new ProfileGenerator(profiles_);
|
| - processor_ = new ProfilerEventsProcessor(generator_);
|
| + Sampler* sampler = logger->sampler();
|
| + processor_ = new ProfilerEventsProcessor(
|
| + generator_, sampler, FLAG_cpu_profiler_sampling_interval);
|
| is_profiling_ = true;
|
| - processor_->StartSynchronously();
|
| // Enumerate stuff we already have in the heap.
|
| ASSERT(isolate_->heap()->HasBeenSetUp());
|
| if (!FLAG_prof_browser_mode) {
|
| @@ -440,12 +445,15 @@ void CpuProfiler::StartProcessorIfNotStarted() {
|
| logger->LogAccessorCallbacks();
|
| LogBuiltins();
|
| // Enable stack sampling.
|
| - Sampler* sampler = logger->sampler();
|
| + if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
|
| + sampler->SetHasProcessingThread(true);
|
| + }
|
| sampler->IncreaseProfilingDepth();
|
| if (!sampler->IsActive()) {
|
| sampler->Start();
|
| need_to_stop_sampler_ = true;
|
| }
|
| + processor_->StartSynchronously();
|
| }
|
| }
|
|
|
| @@ -478,16 +486,19 @@ void CpuProfiler::StopProcessor() {
|
| Logger* logger = isolate_->logger();
|
| Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
|
| sampler->DecreaseProfilingDepth();
|
| - if (need_to_stop_sampler_) {
|
| - sampler->Stop();
|
| - need_to_stop_sampler_ = false;
|
| - }
|
| is_profiling_ = false;
|
| processor_->StopSynchronously();
|
| delete processor_;
|
| delete generator_;
|
| processor_ = NULL;
|
| generator_ = NULL;
|
| + if (Sampler::CanSampleOnProfilerEventsProcessorThread()) {
|
| + sampler->SetHasProcessingThread(false);
|
| + }
|
| + if (need_to_stop_sampler_) {
|
| + sampler->Stop();
|
| + need_to_stop_sampler_ = false;
|
| + }
|
| logger->logging_nesting_ = saved_logging_nesting_;
|
| }
|
|
|
|
|