49
49
void record_submission(uint32_t submission_id)
51
51
std::lock_guard<std::mutex> lock{mutex};
52
timestamps[submission_id] = post_count;
52
submissions.push_back({submission_id, post_count});
55
55
auto latency_for(uint32_t submission_id)
57
57
std::lock_guard<std::mutex> lock{mutex};
59
59
mir::optional_value<uint32_t> latency;
60
auto const it = timestamps.find(submission_id);
62
if (it != timestamps.end())
63
latency = post_count - it->second;
61
for (auto i = submissions.begin(); i != submissions.end(); i++)
63
if (i->buffer_id == submission_id)
65
latency = post_count - i->time;
70
76
unsigned int post_count{0};
71
std::unordered_map<uint32_t, uint32_t> timestamps;
78
// Note that a buffer_id may appear twice in the list as the client is
79
// faster than the compositor and can produce a new frame before the
80
// compositor has measured the previous submisson of the same buffer id.
86
std::deque<Submission> submissions;
74
89
* Note: we're not aiming to check performance in terms of CPU or GPU time processing
78
93
class IdCollectingDB : public mtd::NullDisplayBuffer
81
IdCollectingDB(Stats& stats) : stats{stats} {}
83
96
mir::geometry::Rectangle view_area() const override
85
98
return {{0,0}, {1920, 1080}};
88
101
bool post_renderables_if_optimizable(mg::RenderableList const& renderables) override
91
* Clients are blocked only until the below buffer() goes out of
92
* scope. Thereafter we'll be racing the client thread. So we need
93
* to increment the post_count (represents universal time) here
94
* where the client thread is predictably blocked in its call to
95
* mir_buffer_stream_swap_buffers_sync().
99
103
//the surface will be the frontmost of the renderables
100
104
if (!renderables.empty())
101
105
last = renderables.front()->buffer()->id();
111
114
mg::BufferID last{0};
114
117
class TimeTrackingGroup : public mtd::NullDisplaySyncGroup
117
TimeTrackingGroup(Stats& stats) : stats{stats}, db{stats} {}
120
TimeTrackingGroup(Stats& stats) : stats{stats} {}
119
122
void for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f) override
129
132
std::lock_guard<std::mutex> lock{mutex};
130
133
latency_list.push_back(latency.value());
139
* Sleep a little to make the test more realistic. This way the
140
* client will actually fill the buffer queue. If we don't do this,
141
* then it's like having an infinite refresh rate and the measured
142
* latency would never exceed 1.0. (LP: #1447947)
144
std::this_thread::sleep_for(std::chrono::milliseconds(16));
134
147
float average_latency()
188
201
mir_buffer_stream_swap_buffers_sync(stream);
204
// Wait for the compositor to finish rendering all those frames,
205
// or else we'll be missing some samples and get a spurious average.
206
std::this_thread::sleep_for(std::chrono::milliseconds(500));
191
208
unsigned int const expected_client_buffers = 3;
192
unsigned int const expected_latency = expected_client_buffers - 1;
210
// Note: Using the "early release" optimization without dynamic queue
211
// scaling enabled makes the expected latency possibly up to
212
// nbuffers instead of nbuffers-1. After dynamic queue scaling is
213
// enabled, the average will be lower than this.
214
float const expected_max_latency = expected_client_buffers;
215
float const expected_min_latency = expected_client_buffers - 1;
217
auto observed_latency = display.group.average_latency();
219
// We still have a margin for error here. The client and server will
220
// be scheduled somewhat unpredictably which affects results. Also
221
// affecting results will be the first few frames before the buffer
222
// quere is full (during which there will be no buffer latency).
194
223
float const error_margin = 0.1f;
195
auto observed_latency = display.group.average_latency();
197
// FIXME: LP: #1447947: This actually doesn't work as intended. Raising
198
// the queue length isn't affecting the measured latency for some
199
// reason. But latency too low is better than too high.
200
//EXPECT_THAT(observed_latency, AllOf(Gt(expected_latency-error_margin),
201
// Lt(expected_latency+error_margin)));
203
EXPECT_THAT(observed_latency, Lt(expected_latency+error_margin));
225
EXPECT_THAT(observed_latency, Gt(expected_min_latency-error_margin));
226
EXPECT_THAT(observed_latency, Lt(expected_max_latency+error_margin));