blob: f1cb7e7f71159f8959adc6bef1affccb6944ab1f [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_COMMON_THREAD_PROFILER_H_
#define CHROME_COMMON_THREAD_PROFILER_H_
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/metrics/call_stack_profile_params.h"
#include "components/metrics/legacy_call_stack_profile_builder.h"
namespace service_manager {
class Connector;
}
// PeriodicSamplingScheduler repeatedly schedules periodic sampling of the
// thread through calls to GetTimeToNextCollection(). This class is exposed
// to allow testing.
class PeriodicSamplingScheduler {
public:
PeriodicSamplingScheduler(base::TimeDelta sampling_duration,
double fraction_of_execution_time_to_sample,
base::TimeTicks start_time);
virtual ~PeriodicSamplingScheduler();
// Returns the amount of time between now and the next collection.
base::TimeDelta GetTimeToNextCollection();
protected:
// Virtual to provide seams for test use.
virtual double RandDouble() const;
virtual base::TimeTicks Now() const;
private:
const base::TimeDelta period_duration_;
const base::TimeDelta sampling_duration_;
base::TimeTicks period_start_time_;
DISALLOW_COPY_AND_ASSIGN(PeriodicSamplingScheduler);
};
// ThreadProfiler performs startup and periodic profiling of Chrome
// threads.
class ThreadProfiler {
public:
~ThreadProfiler();
// Creates a profiler for a main thread and immediately starts it. This
// function should only be used when profiling the main thread of a
// process. The returned profiler must be destroyed prior to thread exit to
// stop the profiling. SetMainThreadTaskRunner() should be called after the
// message loop has been started on the thread.
static std::unique_ptr<ThreadProfiler> CreateAndStartOnMainThread();
// Sets the task runner when profiling on the main thread. This occurs in a
// separate call from CreateAndStartOnMainThread so that startup profiling can
// occur prior to message loop start.
void SetMainThreadTaskRunner(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
// Creates a profiler for a child thread and immediately starts it. This
// should be called from a task posted on the child thread immediately after
// thread start. The thread will be profiled until exit.
static void StartOnChildThread(
metrics::CallStackProfileParams::Thread thread);
// Sets the callback to use for reporting browser process profiles. This
// indirection is required to avoid a dependency on unnecessary metrics code
// in child processes.
static void SetBrowserProcessReceiverCallback(
const base::RepeatingCallback<void(base::TimeTicks,
metrics::SampledProfile)>& callback);
// This function must be called within child processes to supply the Service
// Manager's connector, to bind the interface through which a profile is sent
// back to the browser process.
//
// Note that the metrics::CallStackProfileCollector interface also must be
// exposed to the child process, and metrics::mojom::CallStackProfileCollector
// declared in chrome_content_browser_manifest_overlay.json, for the binding
// to succeed.
static void SetServiceManagerConnectorForChildProcess(
service_manager::Connector* connector);
private:
// Creates the profiler. The task runner will be supplied for child threads
// but not for main threads.
ThreadProfiler(
metrics::CallStackProfileParams::Thread thread,
scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner =
scoped_refptr<base::SingleThreadTaskRunner>());
// Posts a task on |owning_thread_task_runner| to start the next periodic
// sampling collection on the completion of the previous collection.
static void OnPeriodicCollectionCompleted(
scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner,
base::WeakPtr<ThreadProfiler> thread_profiler);
// Posts a delayed task to start the next periodic sampling collection.
void ScheduleNextPeriodicCollection();
// Creates a new periodic profiler and initiates a collection with it.
void StartPeriodicSamplingCollection();
scoped_refptr<base::SingleThreadTaskRunner> owning_thread_task_runner_;
const metrics::CallStackProfileParams periodic_profile_params_;
std::unique_ptr<base::StackSamplingProfiler> startup_profiler_;
std::unique_ptr<base::StackSamplingProfiler> periodic_profiler_;
std::unique_ptr<PeriodicSamplingScheduler> periodic_sampling_scheduler_;
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<ThreadProfiler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ThreadProfiler);
};
#endif // CHROME_COMMON_THREAD_PROFILER_H_