| Index: base/profiler/stack_sampling_profiler.cc
|
| diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
|
| index 76ad81df9e87968c4c8ab7fb0316aac44037cb3d..031f40666b6e4ae127e7fc71dcb1e8009a94d83e 100644
|
| --- a/base/profiler/stack_sampling_profiler.cc
|
| +++ b/base/profiler/stack_sampling_profiler.cc
|
| @@ -157,7 +157,11 @@ class StackSamplingProfiler::SamplingThread : public Thread {
|
| const int collection_id;
|
|
|
| const PlatformThreadId target; // ID of The thread being sampled.
|
| - const SamplingParams params; // Information about how to sample.
|
| +
|
| + // Information about how to sample. Not const because they can be updated
|
| + // upon collection completion by |callback|.
|
| + SamplingParams params;
|
| +
|
| const CompletedCallback callback; // Callback made when sampling complete.
|
| WaitableEvent* const finished; // Signaled when all sampling complete.
|
|
|
| @@ -228,8 +232,9 @@ class StackSamplingProfiler::SamplingThread : public Thread {
|
| // Get task runner that is usable from the sampling thread itself.
|
| scoped_refptr<SingleThreadTaskRunner> GetTaskRunnerOnSamplingThread();
|
|
|
| - // Finishes a collection and reports collected data via callback.
|
| - void FinishCollection(CollectionContext* collection);
|
| + // Finishes a collection and reports collected data via callback. Returns
|
| + // whether collection should be restarted per the callback.
|
| + bool FinishCollection(CollectionContext* collection);
|
|
|
| // Records a single sample of a collection.
|
| void RecordSample(CollectionContext* collection);
|
| @@ -473,7 +478,7 @@ StackSamplingProfiler::SamplingThread::GetTaskRunnerOnSamplingThread() {
|
| return Thread::task_runner();
|
| }
|
|
|
| -void StackSamplingProfiler::SamplingThread::FinishCollection(
|
| +bool StackSamplingProfiler::SamplingThread::FinishCollection(
|
| CollectionContext* collection) {
|
| DCHECK_EQ(GetThreadId(), PlatformThread::CurrentId());
|
|
|
| @@ -493,16 +498,14 @@ void StackSamplingProfiler::SamplingThread::FinishCollection(
|
| CallStackProfiles profiles = std::move(collection->profiles);
|
| WaitableEvent* finished = collection->finished;
|
|
|
| - // Remove this collection from the map of known ones. The |collection|
|
| - // parameter is invalid after this point.
|
| - size_t count = active_collections_.erase(collection->collection_id);
|
| - DCHECK_EQ(1U, count);
|
| -
|
| // Run the associated callback, passing the collected profiles.
|
| - callback.Run(std::move(profiles));
|
| + bool restart_collection =
|
| + callback.Run(std::move(profiles), &collection->params);
|
|
|
| // Signal that this collection is finished.
|
| finished->Signal();
|
| +
|
| + return restart_collection;
|
| }
|
|
|
| void StackSamplingProfiler::SamplingThread::RecordSample(
|
| @@ -587,7 +590,14 @@ void StackSamplingProfiler::SamplingThread::RemoveCollectionTask(int id) {
|
| if (found == active_collections_.end())
|
| return;
|
|
|
| - FinishCollection(found->second.get());
|
| + auto* collection = found->second.get();
|
| + FinishCollection(collection);
|
| +
|
| + // Remove this collection from the map of known ones. The |collection|
|
| + // parameter is invalid after this point.
|
| + size_t count = active_collections_.erase(collection->collection_id);
|
| + DCHECK_EQ(1U, count);
|
| +
|
| ScheduleShutdownIfIdle();
|
| }
|
|
|
| @@ -610,19 +620,37 @@ void StackSamplingProfiler::SamplingThread::PerformCollectionTask(int id) {
|
| RecordSample(collection);
|
|
|
| // Update the time of the next sample recording.
|
| - if (UpdateNextSampleTime(collection)) {
|
| - bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
|
| - FROM_HERE,
|
| - Bind(&SamplingThread::PerformCollectionTask, Unretained(this), id),
|
| - std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
|
| - DCHECK(success);
|
| - } else {
|
| - // All capturing has completed so finish the collection. By not re-adding
|
| - // it to the task queue, the collection will "expire" (i.e. no further work
|
| - // will be done). The |collection| variable will be invalid after this call.
|
| - FinishCollection(collection);
|
| + bool collection_finished = !UpdateNextSampleTime(collection);
|
| + if (collection_finished) {
|
| + // All capturing has completed so finish the collection.
|
| + collection_finished = !FinishCollection(collection);
|
| + if (!collection_finished) {
|
| + // Attempt to restart the collection with the new params.
|
| + collection->next_sample_time =
|
| + Time::Now() + collection->params.initial_delay;
|
| + collection->burst = 0;
|
| + collection->sample = 0;
|
| + }
|
| + }
|
| +
|
| + if (collection_finished) {
|
| + // Remove this collection from the map of known ones. The |collection|
|
| + // parameter is invalid after this point.
|
| + size_t count = active_collections_.erase(collection->collection_id);
|
| + DCHECK_EQ(1U, count);
|
| +
|
| + // By not adding it to the task queue, the collection will "expire" (i.e.
|
| + // no further work will be done). The |collection| variable will be invalid
|
| + // after this call.
|
| ScheduleShutdownIfIdle();
|
| + return;
|
| }
|
| +
|
| + bool success = GetTaskRunnerOnSamplingThread()->PostDelayedTask(
|
| + FROM_HERE,
|
| + Bind(&SamplingThread::PerformCollectionTask, Unretained(this), id),
|
| + std::max(collection->next_sample_time - Time::Now(), TimeDelta()));
|
| + DCHECK(success);
|
| }
|
|
|
| void StackSamplingProfiler::SamplingThread::ShutdownTask(int add_events) {
|
|
|