Mir

Merge lp:~vanvugt/mir/simplify-BufferQueue into lp:mir

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Daniel van Vugt
Proposed branch: lp:~vanvugt/mir/simplify-BufferQueue
Merge into: lp:mir
Diff against target: 140 lines (+17/-51)
2 files modified
src/server/compositor/buffer_queue.cpp (+15/-49)
src/server/compositor/buffer_queue.h (+2/-2)
To merge this branch: bzr merge lp:~vanvugt/mir/simplify-BufferQueue
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Information
Chris Halse Rogers Needs Information
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+218794@code.launchpad.net

Commit message

Simplify the new BufferQueue a little bit.

Description of the change

It seems bzr has made a mess of the diff. It might be clearer if you view the source files directly...

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Unexpectedly, this branch appears to solve bug 1317370, consistently.

lp:~vanvugt/mir/simplify-BufferQueue updated
1613. By Daniel van Vugt

Merge latest development-branch

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Wasn't the use of std::vector for current_buffer_users driven by profiling? What is the cost of an unordered_set for this?

The simplification of client_acquire looks good to me.

It seems like the behavioural change here is not checking for !resize_buffer - what is the consequence of that? Is the fact that you can make this change without breaking tests a bug in the existing code, or a bug in the tests?

review: Needs Information
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Found out why this fixes bug 1317370. In this particular test case, with the compositor thread running much faster (1000x) than the client thread, the list current_buffer_users was regularly growing to several thousand elements in size on every client frame. This is obviously unnecessary and explains why this branch is in fact a /correct/ fix for the bug :)

Chris: Re:
73 - if (!resize_buffer && contains(buffer, pending_snapshots))
74 - {
75 + else if (contains(buffer, pending_snapshots))
The new context ("else") already logically guarantees !resize_buffer. It's one of those cases where a simple diff fails to show the whole story.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The compositor rendering more frames than a client is producing is in fact a common occurrence as most apps are mostly idle. So in that case the growth of the current_buffer_users vector is unbounded. Regardless of any performance benefit to the average case, the worst case for a vector is clearly unacceptable (bug 1317370). We need to use a container that guarantees uniqueness of its elements.

Revision history for this message
Chris Halse Rogers (raof) wrote :

Or ensure uniqueness some other way, yes - buffers_sent_to_compositor could suffer the same problem, but doesn't.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

buffers_sent_to_compositor can't suffer the same bug because it gets pruned on every compositor_release().

Revision history for this message
Chris Halse Rogers (raof) wrote :

Indeed, that's my point; current_buffer_users could be likewise pruned.

Actually, now that I say that, why *isn't* it pruned? The compositor is no longer using the current buffer!

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Nice idea. But I just tried that and the bug persists. I think other factors are at play.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I'm sure that std::vector<> was guided by profiling. There should have been a comment to that effect to guide maintainers of the code.

I'd expect vector<> to be more efficient even if I didn't know this - and this is an area of the code we need to be careful of performance.

Even if this stops the bug 1317370 manifesting I'd like to understand better why and the performance implications of this change.

review: Needs Information

Unmerged revisions

1613. By Daniel van Vugt

Merge latest development-branch

1612. By Daniel van Vugt

Simplify more

1611. By Daniel van Vugt

More simplification

1610. By Daniel van Vugt

Simplify user recording

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/server/compositor/buffer_queue.cpp'
2--- src/server/compositor/buffer_queue.cpp 2014-05-07 03:22:19 +0000
3+++ src/server/compositor/buffer_queue.cpp 2014-05-09 03:30:00 +0000
4@@ -135,33 +135,25 @@
5
6 pending_client_notifications.push_back(std::move(complete));
7
8+ mg::Buffer* buf = nullptr;
9 if (!free_buffers.empty())
10 {
11- auto const buffer = free_buffers.back();
12+ buf = free_buffers.back();
13 free_buffers.pop_back();
14- give_buffer_to_client(buffer, std::move(lock));
15- return;
16 }
17-
18- /* No empty buffers, attempt allocating more
19- * TODO: need a good heuristic to switch
20- * between double-buffering to n-buffering
21- */
22- int const allocated_buffers = buffers.size();
23- if (allocated_buffers < nbuffers)
24+ else if (int(buffers.size()) < nbuffers)
25 {
26 auto const& buffer = gralloc->alloc_buffer(the_properties);
27 buffers.push_back(buffer);
28- give_buffer_to_client(buffer.get(), std::move(lock));
29- return;
30+ buf = buffer.get();
31+ }
32+ else if (frame_dropping_enabled && !ready_to_composite_queue.empty())
33+ { /* Last resort, drop oldest buffer from the ready queue */
34+ buf = pop(ready_to_composite_queue);
35 }
36
37- /* Last resort, drop oldest buffer from the ready queue */
38- if (frame_dropping_enabled && !ready_to_composite_queue.empty())
39- {
40- auto const buffer = pop(ready_to_composite_queue);
41- give_buffer_to_client(buffer, std::move(lock));
42- }
43+ if (buf)
44+ give_buffer_to_client(buf, std::move(lock));
45 }
46
47 void mc::BufferQueue::client_release(graphics::Buffer* released_buffer)
48@@ -190,7 +182,8 @@
49 std::unique_lock<decltype(guard)> lock(guard);
50
51 bool const use_current_buffer =
52- should_reuse_current_buffer(user_id) ||
53+ (!current_buffer_users.empty() &&
54+ current_buffer_users.find(user_id) == current_buffer_users.end()) ||
55 ready_to_composite_queue.empty();
56
57 mg::Buffer* buffer_to_release = nullptr;
58@@ -210,7 +203,7 @@
59 }
60
61 buffers_sent_to_compositor.push_back(current_compositor_buffer);
62- current_buffer_users.push_back(user_id);
63+ current_buffer_users.insert(user_id);
64
65 auto const& acquired_buffer = buffer_for(current_compositor_buffer, buffers);
66 if (buffer_to_release)
67@@ -327,10 +320,8 @@
68 if (nbuffers == 1)
69 current_compositor_buffer = buffer;
70 }
71-
72- /* Don't give to the client just yet if there's a pending snapshot */
73- if (!resize_buffer && contains(buffer, pending_snapshots))
74- {
75+ else if (contains(buffer, pending_snapshots))
76+ { /* Don't give to the client just yet if there's a pending snapshot */
77 snapshot_released.wait(lock,
78 [&]{ return !contains(buffer, pending_snapshots); });
79 }
80@@ -348,31 +339,6 @@
81 }
82 }
83
84-bool mc::BufferQueue::should_reuse_current_buffer(void const* user_id)
85-{
86- if (!current_buffer_users.empty())
87- {
88- int size = current_buffer_users.size();
89- for (int i = 0; i < size; ++i)
90- {
91- /* The compositor calling had already acquired
92- * the latest buffer. So it should use the next
93- * buffer available and not reuse the one it already composited.
94- */
95- if (current_buffer_users[i] == user_id)
96- return false;
97- }
98- /* This is new compositor calling so share the latest buffer for
99- * multi-monitor sync
100- */
101- return true;
102- }
103- /* The id list is really only empty the very first time.
104- * False is returned so that the compositor buffer is advanced.
105- */
106- return false;
107-}
108-
109 void mc::BufferQueue::release(
110 mg::Buffer* buffer,
111 std::unique_lock<std::mutex> lock)
112
113=== modified file 'src/server/compositor/buffer_queue.h'
114--- src/server/compositor/buffer_queue.h 2014-05-07 03:22:19 +0000
115+++ src/server/compositor/buffer_queue.h 2014-05-09 03:30:00 +0000
116@@ -24,6 +24,7 @@
117 #include <condition_variable>
118 #include <queue>
119 #include <vector>
120+#include <unordered_set>
121
122 namespace mir
123 {
124@@ -61,7 +62,6 @@
125 private:
126 void give_buffer_to_client(graphics::Buffer* buffer,
127 std::unique_lock<std::mutex> lock);
128- bool should_reuse_current_buffer(void const* user_id);
129 void release(graphics::Buffer* buffer,
130 std::unique_lock<std::mutex> lock);
131
132@@ -74,7 +74,7 @@
133 std::vector<graphics::Buffer*> buffers_sent_to_compositor;
134 std::vector<graphics::Buffer*> pending_snapshots;
135
136- std::vector<void const*> current_buffer_users;
137+ std::unordered_set<void const*> current_buffer_users;
138 graphics::Buffer* current_compositor_buffer;
139
140 std::deque<Callback> pending_client_notifications;

Subscribers

People subscribed via source and target branches