forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
windowed_analyzer.h
159 lines (131 loc) · 5.67 KB
/
windowed_analyzer.h
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
152
153
154
155
156
157
158
159
// 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 UI_LATENCY_WINDOWED_ANALYZER_H_
#define UI_LATENCY_WINDOWED_ANALYZER_H_
#include <cstdint>
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "base/trace_event/traced_value.h"
#include "ui/latency/fixed_point.h"
namespace ui {
// FrameRegionResult encodes window of time where a metric was worst.
// The |sample_count| is the number of samples/frames within the time window
// used to calculate the result. It is reported in case the client wants to
// assess the confidence of the result.
struct FrameRegionResult {
double value = 0;
size_t sample_count = 0;
base::TimeTicks window_begin;
base::TimeTicks window_end;
void AsValueInto(base::trace_event::TracedValue* state) const;
};
namespace frame_metrics {
// Client delegates that are specific to each WindowedAnalyzer.
class WindowedAnalyzerClient {
public:
// The WorstMean,RMS,SMR methods will give TransformResult() a chance to
// modify the results via this delegate.
// This can be used to undo any tranformations applied to values added
// to AddSample, such as conversions to fixed point.
virtual double TransformResult(double result) const = 0;
// TODO(brianderson): Replace WindowedAnalyzer::window_queue_ with a client
// interface here. All latency derived metrics should be able to share a
// common history of values. http://crbug.com/822054
};
// Client delegates that can be shared by multiple WindowedAnalyzers.
// Tracks the current window of time that can be stored as the worst
// window of time if a metric detects it as such.
struct SharedWindowedAnalyzerClient {
SharedWindowedAnalyzerClient() : max_window_size(0) {}
explicit SharedWindowedAnalyzerClient(size_t max_window_size)
: max_window_size(max_window_size) {}
SharedWindowedAnalyzerClient(size_t max_window_size,
base::TimeTicks window_begin,
base::TimeTicks window_end)
: max_window_size(max_window_size),
window_begin(window_begin),
window_end(window_end) {}
// Maximum window size in number of samples.
size_t max_window_size;
// Current window of time for the samples being added.
base::TimeTicks window_begin;
base::TimeTicks window_end;
};
// Detects the worst windows of time for a metric.
// Tracks the current values of the current window of time for the
// mean, RMS, and SMR of a single metric. It maintains a history
// of the recent samples and, for each new sample, updates it's accumulators
// using the oldest and newest samples, without looking at any of the other
// samples in between.
class WindowedAnalyzer {
public:
WindowedAnalyzer(const WindowedAnalyzerClient* client,
const SharedWindowedAnalyzerClient* shared_client);
virtual ~WindowedAnalyzer();
// ResetWosrtValues only resets the memory of worst values encountered,
// without resetting recent sample history.
void ResetWorstValues();
// ResetHistory only resets recent sample history without resetting memory
// of the worst values ecnountered.
void ResetHistory();
// Callers of AddSample will already have calculated weighted values to
// track cumulative results, so just let them pass in the values here
// rather than re-calculating them.
void AddSample(uint32_t value,
uint32_t weight,
uint64_t weighted_value,
uint64_t weighted_root,
const Accumulator96b& weighted_square);
// Returns the worst regions encountered so far.
FrameRegionResult ComputeWorstMean() const;
FrameRegionResult ComputeWorstRMS() const;
FrameRegionResult ComputeWorstSMR() const;
protected:
struct QueueEntry {
uint32_t value = 0;
uint32_t weight = 0;
};
// Updates the result with the current value, if it is worse than the
// value in |result| or if |initialize| is true.
template <typename AccumulatorT>
void UpdateWorst(const AccumulatorT& accumulator,
FrameRegionResult* result,
bool initialize) const {
double current_mean = AsDouble(accumulator) / total_weight_;
if (initialize || current_mean > result->value) {
result->value = current_mean;
result->sample_count = window_queue_.size();
result->window_begin = shared_client_->window_begin;
result->window_end = shared_client_->window_end;
}
}
const WindowedAnalyzerClient* const client_;
const SharedWindowedAnalyzerClient* const shared_client_;
// We need to maintain a history of values so we can
// remove old samples from the accumulators.
base::circular_deque<QueueEntry> window_queue_;
uint64_t total_weight_ = 0;
uint64_t accumulator_ = 0;
uint64_t root_accumulator_ = 0;
Accumulator96b square_accumulator_;
// Internal results that track the worst region so far.
// The time region is stored correctly, however the results are intermediate
// and must be adjusted by result_transform_ and fixed_point_multipler before
// exposure to the client. Furthermore, RMS needs to square root the result
// and SMR needs to square the result.
struct InternalResults {
FrameRegionResult mean;
FrameRegionResult root;
FrameRegionResult square;
};
// Optional since they aren't valid until we've seen enough samples.
// This delay prevents the first couple samples from dominating the result.
base::Optional<InternalResults> results_;
DISALLOW_COPY_AND_ASSIGN(WindowedAnalyzer);
};
} // namespace frame_metrics
} // namespace ui
#endif // UI_LATENCY_WINDOWED_ANALYZER_H_