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
|
// 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 CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
#define CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
#include <vector>
#include "content/browser/scheduler/responsiveness/metric_source.h"
namespace content {
namespace responsiveness {
class Calculator;
class CONTENT_EXPORT Watcher : public base::RefCounted<Watcher>,
public MetricSource::Delegate {
public:
Watcher();
void SetUp();
void Destroy();
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.
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);
// |callback| will either be synchronously invoked, or else never invoked.
using TaskOrEventFinishedCallback = base::OnceCallback<
void(base::TimeTicks, base::TimeTicks, base::TimeTicks)>;
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* calculator_io_ = nullptr;
};
} // namespace responsiveness
} // namespace content
#endif // CONTENT_BROWSER_SCHEDULER_RESPONSIVENESS_WATCHER_H_
|