blob: a05432ca2c18d1cc9b079beba2cc7dec3da2c0ba [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_
#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_
#include <atomic>
#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/scheduler/responsiveness/metric_source.h"
#include "content/common/content_export.h"
#include "content/public/browser/jank_monitor.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
namespace responsiveness {
class CONTENT_EXPORT JankMonitorImpl : public content::JankMonitor,
public MetricSource::Delegate {
public:
JankMonitorImpl();
// JankMonitor implementation:
void AddObserver(content::JankMonitor::Observer* observer) override;
void RemoveObserver(content::JankMonitor::Observer* observer) override;
void SetUp() override;
void Destroy() override;
protected:
~JankMonitorImpl() override;
// MetricSource::Delegate implementation.
void SetUpOnIOThread() override;
void TearDownOnUIThread() override;
void TearDownOnIOThread() override;
void WillRunTaskOnUIThread(const base::PendingTask* task,
bool was_blocked_or_low_priority) override;
void DidRunTaskOnUIThread(const base::PendingTask* task) override;
void WillRunTaskOnIOThread(const base::PendingTask* task,
bool was_blocked_or_low_priority) override;
void DidRunTaskOnIOThread(const base::PendingTask* task) override;
void WillRunEventOnUIThread(const void* opaque_identifier) override;
void DidRunEventOnUIThread(const void* opaque_identifier) override;
// Exposed for tests
virtual void DestroyOnMonitorThread();
virtual void FinishDestroyMetricSource();
virtual std::unique_ptr<MetricSource> CreateMetricSource();
virtual void OnCheckJankiness(); // Timer callback.
bool timer_running() const;
private:
FRIEND_TEST_ALL_PREFIXES(JankinessJankMonitorTest, SetUpDestroy);
class ThreadExecutionState final {
public:
ThreadExecutionState();
~ThreadExecutionState();
void WillRunTaskOrEvent(const void* opaque_identifier);
void DidRunTaskOrEvent(const void* opaque_identifier);
// Checks the jankiness of the target thread. Returns the opaque identifier
// of the janky task or absl::nullopt if the current task is not janky.
absl::optional<const void*> CheckJankiness();
void AssertOnTargetThread();
private:
// Synchronizes the access between the target thread and the monitor thread.
base::Lock lock_;
struct TaskMetadata {
TaskMetadata(base::TimeTicks execution_start_time, const void* identifier)
: execution_start_time(execution_start_time),
identifier(identifier) {}
~TaskMetadata();
base::TimeTicks execution_start_time;
const void* identifier;
};
std::vector<TaskMetadata> task_execution_metadata_;
// Checks some methods are called on the monitor thread.
SEQUENCE_CHECKER(monitor_sequence_checker_);
// Checks some methods are called on the target thread.
SEQUENCE_CHECKER(target_sequence_checker_);
};
void AddObserverOnMonitorThread(Observer* observer);
void RemoveObserverOnMonitorThread(Observer* observer);
void WillRunTaskOrEvent(ThreadExecutionState* thread_exec_state,
const void* opaque_identifier);
void DidRunTaskOrEvent(ThreadExecutionState* thread_exec_state,
const void* opaque_identifier);
// Called in WillRunTaskOrEvent() to start the timer to monitor janks if
// the timer is not running.
void StartTimerIfNecessary();
// Stops the timer on inactivity for longer than a threshold.
void StopTimerIfIdle();
// Sends out notifications.
void OnJankStarted(const void* opaque_identifier);
void OnJankStopped(const void* opaque_identifier);
// Call in DidRunTaskOrEvent() to for notification of jank stops.
void NotifyJankStopIfNecessary(const void* opaque_identifier);
// The source that emits responsiveness events.
std::unique_ptr<content::responsiveness::MetricSource> metric_source_;
std::unique_ptr<ThreadExecutionState> ui_thread_exec_state_;
std::unique_ptr<ThreadExecutionState> io_thread_exec_state_;
// The timer that runs on the monitor sequence to perform periodic check of
// janks.
std::unique_ptr<base::RepeatingTimer> timer_;
// |timer_running_| is equivalent to timer_.IsRunning() except that it is
// thread-safe. It is checked in WillRunTaskOrEvent() (from UI or IO thread)
// to start the timer if necessary. Always updated on the monitor thread to
// mirror the result of timer_.IsRunning().
std::atomic_bool timer_running_;
// The opaque identifier of the janky task. Updated on the monitor thread when
// a janky task is detected. Checked when a task finishes running on UI or IO
// thread to notify observers (from the monitor thread) that the jank has
// stopped.
std::atomic<const void*> janky_task_id_;
// The timestamp of last activity on either UI or IO thread. Checked on the
// monitor thread for stopping the timer on inactivity. Updated on UI or IO
// thread in DidRunTaskOrEvent().
std::atomic<int64_t> last_activity_time_us_;
// Use a dedicated sequence for watching jankiness.
scoped_refptr<base::SequencedTaskRunner> monitor_task_runner_;
// The lock synchronizes access the |observers| from AddObserver(),
// RemoveObserver(), OnJankStarted() and OnJankStopped().
base::Lock observers_lock_;
base::ObserverList<Observer, /* check_empty = */ true>::Unchecked observers_;
// Checks some methods are called on the monitor thread.
SEQUENCE_CHECKER(monitor_sequence_checker_);
};
} // namespace responsiveness.
} // namespace content.
#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_JANK_MONITOR_IMPL_H_