forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhistograms_unittest.cc
177 lines (151 loc) · 6.61 KB
/
histograms_unittest.cc
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// 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.
#include "ui/latency/histograms.h"
#include <algorithm>
#include "base/metrics/bucket_ranges.h"
#include "base/metrics/sample_vector.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/latency/fixed_point.h"
#include "ui/latency/frame_metrics_test_common.h"
namespace ui {
namespace frame_metrics {
// Verifies the ratio boundaries generated internally match the reference
// boundaries.
TEST(FrameMetricsHistogramsTest, RatioBoundariesDirect) {
const TestRatioBoundaries kTestRatioBoundaries;
std::unique_ptr<BoundaryIterator> ratio_impl =
CreateRatioIteratorForTesting();
for (uint32_t boundary : kTestRatioBoundaries.boundaries) {
if (boundary == 0)
continue;
EXPECT_EQ(boundary, ratio_impl->Next());
}
}
// Verifies the VSync boundaries generated internally match the reference
// boundaries.
TEST(FrameMetricsHistogramsTest, VSyncBoundariesDirect) {
std::unique_ptr<BoundaryIterator> vsync_impl =
CreateVSyncIteratorForTesting();
for (uint32_t boundary : kTestVSyncBoundries) {
if (boundary == 0)
continue;
EXPECT_EQ(boundary, vsync_impl->Next());
}
}
// Results should be 0 if no samples have been added yet.
TEST(FrameMetricsHistogramsTest, ResultsAreZeroWithoutSamples) {
RatioHistogram ratio_histogram;
EXPECT_EQ(0, ratio_histogram.ComputePercentiles().values[0]);
EXPECT_EQ(0, ratio_histogram.ComputePercentiles().values[1]);
VSyncHistogram vsync_histogram;
EXPECT_EQ(0, vsync_histogram.ComputePercentiles().values[0]);
EXPECT_EQ(0, vsync_histogram.ComputePercentiles().values[1]);
}
// A non-zero value implies samples were added since, even if those samples
// were zero, they would go into the [0,N) bucket and result in a non-zero
// estimate.
TEST(FrameMetricsHistogramsTest, ResultsAreNonZeroWithSamplesOfZero) {
RatioHistogram ratio_histogram;
ratio_histogram.AddSample(0, 1);
EXPECT_LT(0, ratio_histogram.ComputePercentiles().values[0]);
EXPECT_LT(0, ratio_histogram.ComputePercentiles().values[1]);
VSyncHistogram vsync_histogram;
vsync_histogram.AddSample(0, 1);
EXPECT_LT(0, vsync_histogram.ComputePercentiles().values[0]);
EXPECT_LT(0, vsync_histogram.ComputePercentiles().values[1]);
}
template <typename ReferenceBoundaryT>
void BoundaryTestCommon(const ReferenceBoundaryT& reference_boundaries,
std::unique_ptr<Histogram> histogram) {
PercentileResults percentiles;
for (size_t i = 0; i < reference_boundaries.size() - 1; i++) {
uint64_t bucket_start = reference_boundaries[i];
uint64_t bucket_end = reference_boundaries[i + 1];
// Verify values within the current bucket don't affect percentile.
// This also checks the first value in the bucket.
uint32_t stride = std::max<uint32_t>(1u, (bucket_end - bucket_start) / 8);
for (uint64_t value = bucket_start; value < bucket_end; value += stride) {
histogram->AddSample(value, 1);
percentiles = histogram->ComputePercentiles();
histogram->Reset();
EXPECT_LE(bucket_start, percentiles.values[0]);
EXPECT_GT(bucket_end, percentiles.values[0]);
}
// Verify the value just before the next bucket doesn't affect percentile.
histogram->AddSample(bucket_end - 1, 1);
percentiles = histogram->ComputePercentiles();
histogram->Reset();
EXPECT_LE(bucket_start, percentiles.values[0]);
EXPECT_GT(bucket_end, percentiles.values[0]);
}
}
TEST(FrameMetricsHistogramsTest, RatioBoundaries) {
const TestRatioBoundaries kTestRatioBoundaries;
BoundaryTestCommon(kTestRatioBoundaries, std::make_unique<RatioHistogram>());
}
TEST(FrameMetricsHistogramsTest, VSyncBoundaries) {
const TestRatioBoundaries kTestRatioBoundaries;
BoundaryTestCommon(kTestVSyncBoundries, std::make_unique<VSyncHistogram>());
}
template <typename ReferenceBoundaryT>
void PercentilesTestCommon(const ReferenceBoundaryT& reference_boundaries,
std::unique_ptr<Histogram> histogram,
int percentile_index) {
double percentile = PercentileResults::kPercentiles[percentile_index];
PercentileResults percentiles;
for (size_t i = 0; i < reference_boundaries.size() - 1; i++) {
uint64_t bucket_start = reference_boundaries[i];
uint64_t bucket_end = reference_boundaries[i + 1];
// Add samples to current bucket.
// Where the samples are added in the current bucket should not affect the
// result.
uint32_t stride = std::max<uint32_t>(1u, (bucket_end - bucket_start) / 100);
int samples_added_inside = 0;
for (uint64_t value = bucket_start; value < bucket_end; value += stride) {
histogram->AddSample(value, 10);
samples_added_inside += 10;
}
// Add samples to left and right of current bucket.
// Don't worry about doing this for the left most and right most buckets.
int samples_added_left = 0;
int samples_added_outside = 0;
if (i != 0 && i < reference_boundaries.size() - 2) {
samples_added_outside = 10000;
samples_added_left = samples_added_outside * percentile;
histogram->AddSample(bucket_start / 3, samples_added_left);
histogram->AddSample(bucket_start * 3,
samples_added_outside - samples_added_left);
}
percentiles = histogram->ComputePercentiles();
histogram->Reset();
double index = (samples_added_inside + samples_added_outside) * percentile -
samples_added_left;
double w = index / samples_added_inside;
double expected_value = bucket_end * w + bucket_start * (1.0 - w);
EXPECT_DOUBLE_EQ(expected_value, percentiles.values[percentile_index]);
}
}
TEST(FrameMetricsHistogramsTest, RatioPercentiles50th) {
const TestRatioBoundaries kTestRatioBoundaries;
PercentilesTestCommon(kTestRatioBoundaries,
std::make_unique<RatioHistogram>(), 0);
}
TEST(FrameMetricsHistogramsTest, RatioPercentiles99th) {
const TestRatioBoundaries kTestRatioBoundaries;
PercentilesTestCommon(kTestRatioBoundaries,
std::make_unique<RatioHistogram>(), 1);
}
TEST(FrameMetricsHistogramsTest, VSyncPercentiles50th) {
const TestRatioBoundaries kTestRatioBoundaries;
PercentilesTestCommon(kTestVSyncBoundries, std::make_unique<VSyncHistogram>(),
0);
}
TEST(FrameMetricsHistogramsTest, VSyncPercentiles99th) {
const TestRatioBoundaries kTestRatioBoundaries;
PercentilesTestCommon(kTestVSyncBoundries, std::make_unique<VSyncHistogram>(),
1);
}
} // namespace frame_metrics
} // namespace ui