1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// Copyright 2018 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_WATCHER_H_
#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
#include <variant>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/time/time.h"
#include "content/browser/scheduler/responsiveness/metric_source.h"
#include "content/common/content_export.h"
namespace content {
namespace responsiveness {
class Calculator;
class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher>,
public MetricSource::Delegate {
public:
Watcher();
void SetUp();
void Destroy();
// Must be invoked once-and-only-once, after SetUp(), the first time
// MainMessageLoopRun() reaches idle (i.e. done running all tasks queued
// during startup). This will be used as a signal for the true end of
// "startup" and the beginning of recording Browser.MainThreadsCongestion.
void OnFirstIdle();
protected:
friend class base::RefCounted<Watcher>;
// Exposed for tests.
virtual std::unique_ptr<Calculator> CreateCalculator();
virtual std::unique_ptr<MetricSource> CreateMetricSource();
~Watcher() override;
// Delegate interface 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;
private:
FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskForwarding);
FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, TaskNesting);
FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, NativeEvents);
FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, BlockedOrLowPriorityTask);
FRIEND_TEST_ALL_PREFIXES(ResponsivenessWatcherTest, DelayedTask);
// Metadata for currently running tasks and events is needed to track whether
// or not they caused reentrancy.
struct Metadata {
explicit Metadata(const void* identifier,
bool was_blocked_or_low_priority,
base::TimeTicks execution_start_time);
// An opaque identifier for the task or event.
//
// `identifier` is not a raw_ptr<...> for performance reasons (based on
// analysis of sampling profiler data and tab_search:top100:2020).
RAW_PTR_EXCLUSION const void* const identifier;
// Whether the task was at some point in a queue that was blocked or low
// priority.
const bool was_blocked_or_low_priority;
// The time at which the task or event started running.
const base::TimeTicks execution_start_time;
// Whether the task or event has caused reentrancy.
bool caused_reentrancy = false;
};
// This is called when |metric_source_| finishes destruction.
void FinishDestroyMetricSource();
// Common implementations for the thread-specific methods.
void WillRunTask(const base::PendingTask* task,
bool was_blocked_or_low_priority,
std::vector<Metadata>* currently_running_metadata);
// TODO(crbug.com/40287434): After the "ReduceCpuUtilization2" feature is
// cleaned up (~January 2025), remove the std::variant in favor of a
// base::FunctionRef.
using TaskOrEventFinishedSignature = void(base::TimeTicks,
base::TimeTicks,
base::TimeTicks);
using TaskOrEventFinishedCallback =
base::FunctionRef<TaskOrEventFinishedSignature>;
// |callback| will either be synchronously invoked, or else never invoked.
void DidRunTask(const base::PendingTask* task,
std::vector<Metadata>* currently_running_metadata,
int* mismatched_task_identifiers,
TaskOrEventFinishedCallback callback);
// The source that emits responsiveness events.
std::unique_ptr<MetricSource> metric_source_;
// The following members are all affine to the UI thread.
std::unique_ptr<Calculator> calculator_;
// Metadata for currently running tasks and events on the UI thread.
std::vector<Metadata> currently_running_metadata_ui_;
// Task identifiers should only be mismatched once, since the Watcher may
// register itself during a Task execution, and thus doesn't capture the
// initial WillRunTask() callback.
int mismatched_task_identifiers_ui_ = 0;
// Event identifiers should be mismatched at most once, since the Watcher may
// register itself during an event execution, and thus doesn't capture the
// initial WillRunEventOnUIThread callback.
int mismatched_event_identifiers_ui_ = 0;
// The following members are all affine to the IO thread.
std::vector<Metadata> currently_running_metadata_io_;
int mismatched_task_identifiers_io_ = 0;
// The implementation of this class guarantees that |calculator_io_| will be
// non-nullptr and point to a valid object any time it is used on the IO
// thread. To ensure this, the first task that this class posts onto the IO
// thread sets |calculator_io_|. On destruction, this class first tears down
// all consumers of |calculator_io_|, and then clears the member and destroys
// Calculator.
// `calculator_io_` is not a raw_ptr<...> because Calculator isn't supported
// in raw_ptr for performance reasons. See crbug.com/1287151.
RAW_PTR_EXCLUSION Calculator* calculator_io_ = nullptr;
};
} // namespace responsiveness
} // namespace content
#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
|