Merge lp:~kdub/mir/fix-1579076 into lp:mir
- fix-1579076
- Merge into development-branch
Status: | Merged |
---|---|
Merged at revision: | 3520 |
Proposed branch: | lp:~kdub/mir/fix-1579076 |
Merge into: | lp:mir |
Diff against target: |
283 lines (+131/-34) 3 files modified
src/client/buffer_vault.cpp (+30/-19) src/client/buffer_vault.h (+2/-0) tests/unit-tests/client/test_buffer_vault.cpp (+99/-15) |
To merge this branch: | bzr merge lp:~kdub/mir/fix-1579076 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Needs Fixing | |
Cemil Azizoglu (community) | Approve | ||
Daniel van Vugt | Abstain | ||
Review via email: mp+294036@code.launchpad.net |
Commit message
fix lp: #1579076 by correcting a situation where an incorrectly-sized buffer didn't end up getting freed, resulting in performance degradation.
Consolidates how set_size and set_scale works under NBS as a bonus, now both will immediately free buffers that can be freed, and allocate the buffers back once a wait situation is encountered.
Description of the change
fix lp: #1579076 by correcting a situation where an incorrectly-sized buffer didn't end up getting freed, resulting in performance degradation.
Consolidates how set_size and set_scale works under NBS as a bonus, now both will immediately free buffers that can be freed, and allocate the buffers back once a wait situation is encountered.
problem manifested itself on krillin + unity8-dash as being ~10fps lower than vsync on the device, as it was operating effectively as double-buffered, when on this device, triple-buffered operation is needed to keep up with rendering.
tested with full stack against the bug on flo, krillin, arale. Will be ported to 0.23 to unblock that release.
Mir CI Bot (mir-ci-bot) wrote : | # |
Daniel van Vugt (vanvugt) wrote : | # |
Sounds good... Does this allow us to remove the hackish fix for bug 1557442? (since this MP sounds like the correct solution)
Kevin DuBois (kdub) wrote : | # |
I think that 1557442 is more appropriately a duplicate of (1579076) than of 1557962, so will change accordingly.. The overallocation strategy (which could be improved to be more dynamic, but imho is not a hack) is probably still needed for 1557962
Daniel van Vugt (vanvugt) wrote : | # |
I shall try to develop a way to test this manually soon...
Daniel van Vugt (vanvugt) wrote : | # |
Sorry, I tried and can't easily test this right now, due to too many recent changes in buffer_vault.cpp to unwind and try one thing at a time.
I am concerned we're going downhill with code quality and maturity though. This branch has been forced into lp:mir/0.23 already without review or approval, apparently in a rush to release Mir 0.23.0 while we haven't given the new NBS code time to cool down, stabilize and mature yet. This is not good practice.
Kevin DuBois (kdub) wrote : | # |
> I am concerned we're going downhill with code quality and maturity though.
> This branch has been forced into lp:mir/0.23 already without review or
> approval, apparently in a rush to release Mir 0.23.0 while we haven't given
> the new NBS code time to cool down, stabilize and mature yet. This is not good
> practice.
The MP fixes a bug that was detected in full system integration. This branch should make things more stable and performant, not less.
This MP is included in the 0.23 branch already, but this is mostly just preparation work. We're blocked awaiting silo 31 landing, so things should come together at the same time.
Daniel van Vugt (vanvugt) wrote : | # |
Yes, it's an unavoidable truth that we're not going to finish finding all the bugs and build confidence in maturity till it's in production and more people are using it.
I guess my concerns are less about NBS and more about the bigger machine it is part of. We don't have anything resembling a stable long-term support Ubuntu Touch channel that only gets bug fixes. Admittedly there is a good argument that it is too early for that.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Kevin DuBois (kdub) wrote : | # |
^lp: #1576690
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Daniel van Vugt (vanvugt) wrote : | # |
And bug 1576690 again.
Andreas Pokorny (andreas-pokorny) wrote : | # |
just retriggering .. ci seems to be normal again.. at least the auth error of the trigger job is gone
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Daniel van Vugt (vanvugt) wrote : | # |
The failure is bug 1576690 and not this branch. Try again.
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Daniel van Vugt (vanvugt) wrote : | # |
Failure is bug 1584603
Mir CI Bot (mir-ci-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Daniel van Vugt (vanvugt) wrote : | # |
Failure is not related to this branch. It's a krillin device hiccup:
04:59:13 2016/05/25 04:59:13 error pushing: cannot stat '/var/lib/
Preview Diff
1 | === modified file 'src/client/buffer_vault.cpp' |
2 | --- src/client/buffer_vault.cpp 2016-05-04 14:42:48 +0000 |
3 | +++ src/client/buffer_vault.cpp 2016-05-06 18:40:55 +0000 |
4 | @@ -122,7 +122,7 @@ |
5 | |
6 | mcl::NoTLSFuture<std::shared_ptr<mcl::Buffer>> mcl::BufferVault::withdraw() |
7 | { |
8 | - std::lock_guard<std::mutex> lk(mutex); |
9 | + std::unique_lock<std::mutex> lk(mutex); |
10 | if (disconnected_) |
11 | BOOST_THROW_EXCEPTION(std::logic_error("server_disconnected")); |
12 | mcl::NoTLSPromise<std::shared_ptr<mcl::Buffer>> promise; |
13 | @@ -146,6 +146,15 @@ |
14 | else |
15 | { |
16 | promises.emplace_back(std::move(promise)); |
17 | + |
18 | + auto s = size; |
19 | + bool allocate_buffer = (current_buffer_count < needed_buffer_count); |
20 | + if (allocate_buffer) |
21 | + current_buffer_count++; |
22 | + lk.unlock(); |
23 | + |
24 | + if (allocate_buffer) |
25 | + alloc_buffer(s, format, usage); |
26 | } |
27 | return future; |
28 | } |
29 | @@ -198,12 +207,12 @@ |
30 | { |
31 | auto id = it->first; |
32 | buffers.erase(it); |
33 | - lk.unlock(); |
34 | - |
35 | - free_buffer(id); |
36 | if (should_decrease_count) |
37 | current_buffer_count--; |
38 | - else |
39 | + lk.unlock(); |
40 | + |
41 | + free_buffer(id); |
42 | + if (!should_decrease_count) |
43 | alloc_buffer(size, format, usage); |
44 | return; |
45 | } |
46 | @@ -221,15 +230,6 @@ |
47 | } |
48 | } |
49 | |
50 | -//TODO: the server will currently spam us with a lot of resize messages at once, |
51 | -// and we want to delay the IPC transactions for resize. If we could rate-limit |
52 | -// the incoming messages, we should should consolidate the scale and size functions |
53 | -void mcl::BufferVault::set_size(geom::Size sz) |
54 | -{ |
55 | - std::lock_guard<std::mutex> lk(mutex); |
56 | - size = sz; |
57 | -} |
58 | - |
59 | void mcl::BufferVault::disconnected() |
60 | { |
61 | std::lock_guard<std::mutex> lk(mutex); |
62 | @@ -239,17 +239,28 @@ |
63 | |
64 | void mcl::BufferVault::set_scale(float scale) |
65 | { |
66 | + std::unique_lock<std::mutex> lk(mutex); |
67 | + set_size(lk, size * scale); |
68 | +} |
69 | + |
70 | +void mcl::BufferVault::set_size(geom::Size new_size) |
71 | +{ |
72 | + std::unique_lock<std::mutex> lk(mutex); |
73 | + set_size(lk, new_size); |
74 | +} |
75 | + |
76 | +void mcl::BufferVault::set_size(std::unique_lock<std::mutex>& lk, geometry::Size new_size) |
77 | +{ |
78 | + if (new_size == size) |
79 | + return; |
80 | std::vector<int> free_ids; |
81 | - std::unique_lock<std::mutex> lk(mutex); |
82 | - auto new_size = size * scale; |
83 | - if (new_size == size) |
84 | - return; |
85 | size = new_size; |
86 | for (auto it = buffers.begin(); it != buffers.end();) |
87 | { |
88 | auto buffer = checked_buffer_from_map(it->first); |
89 | if ((it->second == Owner::Self) && (buffer->size() != size)) |
90 | { |
91 | + current_buffer_count--; |
92 | free_ids.push_back(it->first); |
93 | it = buffers.erase(it); |
94 | } |
95 | @@ -261,7 +272,7 @@ |
96 | lk.unlock(); |
97 | |
98 | for(auto& id : free_ids) |
99 | - realloc_buffer(id, new_size, format, usage); |
100 | + free_buffer(id); |
101 | } |
102 | |
103 | void mcl::BufferVault::increase_buffer_count() |
104 | |
105 | === modified file 'src/client/buffer_vault.h' |
106 | --- src/client/buffer_vault.h 2016-05-04 14:42:48 +0000 |
107 | +++ src/client/buffer_vault.h 2016-05-06 18:40:55 +0000 |
108 | @@ -78,6 +78,8 @@ |
109 | void alloc_buffer(geometry::Size size, MirPixelFormat format, int usage); |
110 | void free_buffer(int free_id); |
111 | void realloc_buffer(int free_id, geometry::Size size, MirPixelFormat format, int usage); |
112 | + void set_size(std::unique_lock<std::mutex>& lk, geometry::Size new_size); |
113 | + |
114 | std::shared_ptr<Buffer> checked_buffer_from_map(int id); |
115 | |
116 | std::shared_ptr<ClientBufferFactory> const platform_factory; |
117 | |
118 | === modified file 'tests/unit-tests/client/test_buffer_vault.cpp' |
119 | --- tests/unit-tests/client/test_buffer_vault.cpp 2016-05-04 12:24:20 +0000 |
120 | +++ tests/unit-tests/client/test_buffer_vault.cpp 2016-05-06 18:40:55 +0000 |
121 | @@ -326,6 +326,8 @@ |
122 | |
123 | TEST_F(StartedBufferVault, reallocates_incoming_buffers_of_incorrect_size_with_immediate_response) |
124 | { |
125 | + vault.set_size(new_size); |
126 | + |
127 | EXPECT_CALL(mock_requests, free_buffer(package.buffer_id())); |
128 | EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_)) |
129 | .WillOnce(Invoke( |
130 | @@ -334,17 +336,17 @@ |
131 | vault.wire_transfer_inbound(package4.buffer_id()); |
132 | })); |
133 | |
134 | - vault.set_size(new_size); |
135 | vault.wire_transfer_inbound(package.buffer_id()); |
136 | Mock::VerifyAndClearExpectations(&mock_requests); |
137 | } |
138 | |
139 | TEST_F(StartedBufferVault, reallocates_incoming_buffers_of_incorrect_size_with_delayed_response) |
140 | { |
141 | + vault.set_size(new_size); |
142 | + |
143 | EXPECT_CALL(mock_requests, free_buffer(package.buffer_id())); |
144 | EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_)); |
145 | |
146 | - vault.set_size(new_size); |
147 | vault.wire_transfer_inbound(package.buffer_id()); |
148 | vault.wire_transfer_inbound(package4.buffer_id()); |
149 | EXPECT_THAT(vault.withdraw().get()->size(), Eq(new_size)); |
150 | @@ -361,9 +363,9 @@ |
151 | Mock::VerifyAndClearExpectations(&mock_requests); |
152 | } |
153 | |
154 | -TEST_F(StartedBufferVault, simply_setting_size_triggers_no_server_interations) |
155 | +TEST_F(StartedBufferVault, setting_size_frees_unneeded_buffers_right_away) |
156 | { |
157 | - EXPECT_CALL(mock_requests, free_buffer(_)).Times(0); |
158 | + EXPECT_CALL(mock_requests, free_buffer(_)).Times(3); |
159 | EXPECT_CALL(mock_requests, allocate_buffer(_,_,_)).Times(0); |
160 | auto const cycles = 30u; |
161 | geom::Size new_size(80, 100); |
162 | @@ -450,21 +452,14 @@ |
163 | EXPECT_CALL(mock_requests, free_buffer(_)) |
164 | .Times(initial_nbuffers); |
165 | |
166 | - auto buffer = vault.withdraw().get(); |
167 | vault.set_scale(scale); |
168 | - vault.deposit(buffer); |
169 | - vault.wire_transfer_outbound(buffer); |
170 | - vault.wire_transfer_inbound(package.buffer_id()); |
171 | |
172 | - for(auto i = 0; i < 100; i++) |
173 | + for(auto i = 0u; i < initial_nbuffers; i++) |
174 | { |
175 | auto b = vault.withdraw().get(); |
176 | - EXPECT_THAT(b->size(), Eq(new_size)); |
177 | vault.deposit(b); |
178 | - b->received(); |
179 | - vault.wire_transfer_outbound(b); |
180 | - vault.wire_transfer_inbound(buffers[(i+1)%3].buffer_id()); |
181 | } |
182 | + |
183 | Mock::VerifyAndClearExpectations(&mock_requests); |
184 | } |
185 | |
186 | @@ -572,6 +567,95 @@ |
187 | vault.wire_transfer_inbound(first_id); |
188 | |
189 | EXPECT_THAT(vault.withdraw().get()->rpc_id(), Ne(first_id)); |
190 | - |
191 | - |
192 | +} |
193 | + |
194 | +//LP: #1579076 |
195 | +TEST_F(StartedBufferVault, doesnt_let_buffers_stagnate_after_resize) |
196 | +{ |
197 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
198 | + .Times(3); |
199 | + vault.set_size(new_size); |
200 | + |
201 | + EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_)) |
202 | + .Times(1); |
203 | + auto buffer_future = vault.withdraw(); |
204 | + vault.wire_transfer_inbound(package4.buffer_id()); |
205 | + EXPECT_THAT(buffer_future.get()->size(), Eq(new_size)); |
206 | + Mock::VerifyAndClearExpectations(&mock_requests); |
207 | +} |
208 | + |
209 | +TEST_F(StartedBufferVault, doesnt_free_buffers_in_the_driver_after_resize) |
210 | +{ |
211 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
212 | + .Times(2); |
213 | + auto buffer = vault.withdraw().get(); |
214 | + vault.set_size(new_size); |
215 | + Mock::VerifyAndClearExpectations(&mock_requests); |
216 | + |
217 | + vault.deposit(buffer); |
218 | + vault.wire_transfer_outbound(buffer); |
219 | + |
220 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
221 | + .Times(1); |
222 | + vault.wire_transfer_inbound(buffer->rpc_id()); |
223 | + Mock::VerifyAndClearExpectations(&mock_requests); |
224 | +} |
225 | + |
226 | +TEST_F(StartedBufferVault, doesnt_free_buffers_with_content_after_resize) |
227 | +{ |
228 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
229 | + .Times(2); |
230 | + auto buffer = vault.withdraw().get(); |
231 | + vault.deposit(buffer); |
232 | + vault.set_size(new_size); |
233 | + Mock::VerifyAndClearExpectations(&mock_requests); |
234 | + |
235 | + vault.wire_transfer_outbound(buffer); |
236 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
237 | + .Times(1); |
238 | + vault.wire_transfer_inbound(buffer->rpc_id()); |
239 | + Mock::VerifyAndClearExpectations(&mock_requests); |
240 | +} |
241 | + |
242 | +TEST_F(StartedBufferVault, doesnt_free_buffers_if_size_is_the_same) |
243 | +{ |
244 | + EXPECT_CALL(mock_requests, free_buffer(_)) |
245 | + .Times(0); |
246 | + vault.set_size(size); |
247 | + Mock::VerifyAndClearExpectations(&mock_requests); |
248 | +} |
249 | + |
250 | +TEST_F(StartedBufferVault, delays_allocation_if_not_needed) |
251 | +{ |
252 | + vault.set_size(new_size); |
253 | + |
254 | + EXPECT_CALL(mock_requests, allocate_buffer(new_size,_,_)) |
255 | + .Times(1) |
256 | + .WillOnce(Invoke( |
257 | + [&, this](geom::Size, MirPixelFormat, int) |
258 | + { |
259 | + vault.wire_transfer_inbound(package4.buffer_id()); |
260 | + })); |
261 | + |
262 | + for(auto i = 0u; i < 10u; i++) |
263 | + { |
264 | + auto buffer = vault.withdraw().get(); |
265 | + vault.deposit(buffer); |
266 | + buffer->received(); |
267 | + vault.wire_transfer_outbound(buffer); |
268 | + vault.wire_transfer_inbound(buffer->rpc_id()); |
269 | + } |
270 | +} |
271 | + |
272 | +TEST_F(StartedBufferVault, can_increase_count_after_resize) |
273 | +{ |
274 | + auto num_allocations = 4u; |
275 | + EXPECT_CALL(mock_requests, allocate_buffer(_,_,_)) |
276 | + .Times(num_allocations); |
277 | + |
278 | + vault.increase_buffer_count(); |
279 | + vault.set_size(new_size); |
280 | + |
281 | + for(auto i = 0u; i < num_allocations + 1; i++) |
282 | + vault.withdraw(); |
283 | } |
PASSED: Continuous integration, rev:3504 /mir-jenkins. ubuntu. com/job/ mir-ci/ 955/ /mir-jenkins. ubuntu. com/job/ build-mir/ 1022 /mir-jenkins. ubuntu. com/job/ build-0- fetch/1068 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 1059 /mir-jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial/ 1059 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1032 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= clang,platform= mesa,release= vivid+overlay/ 1032/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1032 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= amd64,compiler= gcc,platform= mesa,release= xenial/ 1032/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1032 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= cross-armhf, compiler= gcc,platform= android, release= vivid+overlay/ 1032/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1032 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= android, release= vivid+overlay/ 1032/artifact/ output/ *zip*/output. zip /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1032 /mir-jenkins. ubuntu. com/job/ build-2- binpkg- mir/arch= i386,compiler= gcc,platform= mesa,release= xenial/ 1032/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /mir-jenkins. ubuntu. com/job/ mir-ci/ 955/rebuild
https:/