Merge lp:~gordallott/unity/more-dash-speedups into lp:unity

Proposed by Gord Allott
Status: Merged
Approved by: Mirco Müller
Approved revision: no longer in the source branch.
Merged at revision: 1518
Proposed branch: lp:~gordallott/unity/more-dash-speedups
Merge into: lp:unity
Diff against target: 286 lines (+145/-15)
4 files modified
plugins/unityshell/src/ResultRendererTile.cpp (+10/-5)
plugins/unityshell/src/ResultViewGrid.cpp (+124/-8)
plugins/unityshell/src/ResultViewGrid.h (+8/-1)
tests/TestResultView.cpp (+3/-1)
To merge this branch: bzr merge lp:~gordallott/unity/more-dash-speedups
Reviewer Review Type Date Requested Status
Mirco Müller (community) Approve
Review via email: mp+74569@code.launchpad.net

Description of the change

two speedups, first the dash only draws the results that are physically on the screen, anything not expanded or scrolled off will not get drawn

secondly we only pre-load the majority of results when the result view is expanded.

I tried to make it work so that we only pre-loaded a few screens worth even then, but nux doesn't give you a nice way of knowing if you have been scrolled, so it just lead to lots of waiting around for icons to load, not fun

all in all we should be much nicer on your memory with this branch

To post a comment you must log in.
Revision history for this message
Mirco Müller (macslow) wrote :

Very nice! Approved!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/unityshell/src/ResultRendererTile.cpp'
2--- plugins/unityshell/src/ResultRendererTile.cpp 2011-09-05 00:46:13 +0000
3+++ plugins/unityshell/src/ResultRendererTile.cpp 2011-09-08 09:40:25 +0000
4@@ -75,6 +75,10 @@
5 nux::Geometry& geometry,
6 int x_offset, int y_offset)
7 {
8+ TextureContainer* container = row.renderer<TextureContainer*>();
9+ if (container == nullptr)
10+ return;
11+
12 std::string row_text = row.name;
13 std::string row_iconhint = row.icon_hint;
14 PlacesStyle* style = PlacesStyle::GetDefault();
15@@ -99,8 +103,6 @@
16 geometry.height,
17 col);
18
19- TextureContainer* container = row.renderer<TextureContainer*>();
20-
21 if (container->blurred_icon)
22 {
23 GfxContext.QRP_1Tex(geometry.x + ((geometry.width - 58) / 2) - x_offset,
24@@ -221,9 +223,12 @@
25
26 void ResultRendererTile::Preload(Result& row)
27 {
28- row.set_renderer(new TextureContainer());
29- LoadIcon(row);
30- LoadText(row);
31+ if (row.renderer<TextureContainer*>() == nullptr)
32+ {
33+ row.set_renderer(new TextureContainer());
34+ LoadIcon(row);
35+ LoadText(row);
36+ }
37 }
38
39 void ResultRendererTile::Unload(Result& row)
40
41=== modified file 'plugins/unityshell/src/ResultViewGrid.cpp'
42--- plugins/unityshell/src/ResultViewGrid.cpp 2011-09-08 03:04:04 +0000
43+++ plugins/unityshell/src/ResultViewGrid.cpp 2011-09-08 09:40:25 +0000
44@@ -52,6 +52,7 @@
45 , active_index_(-1)
46 , selected_index_(-1)
47 , preview_row_(0)
48+ , lazy_load_queued_(false)
49 , last_mouse_down_x_(-1)
50 , last_mouse_down_y_(-1)
51 {
52@@ -89,6 +90,66 @@
53 {
54 }
55
56+gboolean ResultViewGrid::OnLazyLoad (gpointer data)
57+{
58+ ResultViewGrid *self = (ResultViewGrid*)data;
59+ self->DoLazyLoad();
60+ return FALSE;
61+}
62+
63+void ResultViewGrid::QueueLazyLoad()
64+{
65+ if (lazy_load_queued_ == false)
66+ {
67+ g_timeout_add(0, (GSourceFunc)(&ResultViewGrid::OnLazyLoad), this);
68+ lazy_load_queued_ = true;
69+ }
70+}
71+
72+void ResultViewGrid::DoLazyLoad()
73+{
74+ lazy_load_queued_ = false;
75+ // FIXME - so this code was nice, it would only load the visible entries on the screen
76+ // however nux does not give us a good enough indicator right now that we are scrolling,
77+ // thus if you scroll more than a screen in one frame, you will end up with at least one frame where
78+ // no icons are displayed (they have not been preloaded yet) - it sucked. we should fix this next cycle when we can break api
79+ //~ int index = 0;
80+//~
81+ //~ ResultListBounds visible_bounds = GetVisableResults();
82+ //~ int lower_bound = std::get<0>(visible_bounds);
83+ //~ int upper_bound = std::get<1>(visible_bounds);
84+//~
85+ //~ ResultList::iterator it;
86+ //~ for (it = results_.begin(); it != results_.end(); it++)
87+ //~ {
88+ //~ if (index >= lower_bound && index <= upper_bound)
89+ //~ {
90+ //~ renderer_->Preload((*it));
91+ //~ }
92+ //~ index++;
93+ //~ }
94+
95+ // instead we will just pre-load all the items if expanded or just one row if not
96+ int index = 0;
97+ int items_per_row = GetItemsPerRow();
98+ ResultList::iterator it;
99+ for (it = results_.begin(); it != results_.end(); it++)
100+ {
101+ if ((!expanded && index < items_per_row) || expanded)
102+ {
103+ renderer_->Preload((*it));
104+ }
105+
106+ if (!expanded && index >= items_per_row)
107+ break; //early exit
108+
109+ index++;
110+ }
111+
112+ QueueDraw();
113+}
114+
115+
116 int ResultViewGrid::GetItemsPerRow()
117 {
118 int items_per_row = (GetGeometry().width - (padding * 2)) / (renderer_->width + horizontal_spacing);
119@@ -135,14 +196,18 @@
120
121 void ResultViewGrid::AddResult(Result& result)
122 {
123- ResultView::AddResult(result);
124+ results_.push_back(result);
125+
126 SizeReallocate();
127+ QueueLazyLoad();
128+ NeedRedraw();
129 }
130
131 void ResultViewGrid::RemoveResult(Result& result)
132 {
133 ResultView::RemoveResult(result);
134 SizeReallocate();
135+ QueueLazyLoad();
136 }
137
138 void ResultViewGrid::SizeReallocate()
139@@ -150,7 +215,7 @@
140 //FIXME - needs to use the geometry assigned to it, but only after a layout
141 int items_per_row = GetItemsPerRow();
142
143- int total_rows = (results_.size() / items_per_row);
144+ int total_rows = (results_.size() / items_per_row) + 1;
145 int total_height = 0;
146
147 if (expanded)
148@@ -401,11 +466,63 @@
149 long ResultViewGrid::ComputeLayout2()
150 {
151 SizeReallocate();
152+ QueueLazyLoad();
153 long ret = ResultView::ComputeLayout2();
154 return ret;
155
156 }
157
158+
159+typedef std::tuple <int, int> ResultListBounds;
160+ResultListBounds ResultViewGrid::GetVisableResults()
161+{
162+ int items_per_row = GetItemsPerRow();
163+ int start, end;
164+
165+ if (!expanded)
166+ {
167+ // we are not expanded, so the bounds are known
168+ start = 0;
169+ end = items_per_row - 1;
170+ }
171+ else
172+ {
173+ //find the row we start at
174+ int absolute_y = GetAbsoluteY();
175+ uint row_size = renderer_->height + vertical_spacing;
176+
177+ if (absolute_y < 0)
178+ {
179+ // we are scrolled up a little,
180+ int row_index = abs(absolute_y) / row_size;
181+ start = row_index * items_per_row;
182+ }
183+ else
184+ {
185+ start = 0;
186+ }
187+
188+ if (absolute_y + GetAbsoluteHeight() > GetToplevel()->GetAbsoluteHeight())
189+ {
190+ // our elements overflow the visable viewport
191+ int visible_height = (GetToplevel()->GetAbsoluteHeight() - std::max(absolute_y, 0));
192+ visible_height = std::min(visible_height, absolute_y + GetAbsoluteHeight());
193+
194+ int visible_rows = std::ceil(visible_height / static_cast<float>(row_size));
195+ end = start + (visible_rows * items_per_row) + items_per_row;
196+ }
197+ else
198+ {
199+ end = results_.size() - 1;
200+ }
201+ }
202+
203+ start = std::max(start, 0);
204+ end = std::min(end, static_cast<int>(results_.size()) - 1);
205+
206+ return ResultListBounds(start, end);
207+}
208+
209 void ResultViewGrid::Draw(nux::GraphicsEngine& GfxContext, bool force_draw)
210 {
211 GfxContext.PushClippingRectangle(GetGeometry());
212@@ -425,14 +542,13 @@
213 int y_position = padding + GetGeometry().y;
214 nux::Area* top_level_parent = GetToplevel();
215
216+ ResultListBounds visible_bounds = GetVisableResults();
217+
218 for (uint row_index = 0; row_index <= total_rows; row_index++)
219 {
220- // check if the row is displayed on the screen,
221- // FIXME - optimisation - replace 2048 with the height of the displayed viewport
222- // or at the very least, with the largest monitor resolution
223- //~ if ((y_position + renderer_->height) + absolute_y >= 0
224- //~ && (y_position - renderer_->height) + absolute_y <= top_level_parent->GetGeometry().height)
225- if (1)
226+ int row_lower_bound = row_index * items_per_row;
227+ if (row_lower_bound >= std::get<0>(visible_bounds) &&
228+ row_lower_bound <= std::get<1>(visible_bounds))
229 {
230 int x_position = padding + GetGeometry().x;
231 for (int column_index = 0; column_index < items_per_row; column_index++)
232
233=== modified file 'plugins/unityshell/src/ResultViewGrid.h'
234--- plugins/unityshell/src/ResultViewGrid.h 2011-08-31 23:28:44 +0000
235+++ plugins/unityshell/src/ResultViewGrid.h 2011-09-08 09:40:25 +0000
236@@ -53,7 +53,6 @@
237 nux::Property<int> padding;
238
239
240-
241 protected:
242 void MouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags);
243 void MouseClick(int x, int y, unsigned long button_flags, unsigned long key_flags);
244@@ -76,6 +75,13 @@
245 virtual long ComputeLayout2();
246
247 private:
248+ typedef std::tuple <int, int> ResultListBounds;
249+ ResultListBounds GetVisableResults();
250+
251+ static gboolean OnLazyLoad (gpointer data);
252+ void QueueLazyLoad();
253+ void DoLazyLoad();
254+
255 int GetItemsPerRow();
256 void SizeReallocate();
257 void PositionPreview();
258@@ -87,6 +93,7 @@
259 uint preview_row_;
260 std::string focused_uri_;
261
262+ bool lazy_load_queued_;
263 int last_mouse_down_x_;
264 int last_mouse_down_y_;
265 std::string current_drag_uri_;
266
267=== modified file 'tests/TestResultView.cpp'
268--- tests/TestResultView.cpp 2011-08-31 14:14:18 +0000
269+++ tests/TestResultView.cpp 2011-09-08 09:40:25 +0000
270@@ -88,6 +88,8 @@
271 iters_.push_back(iter);
272 }
273
274+ DeeModelTag* tag = dee_model_register_tag(model_, NULL);
275+
276 LOG_DEBUG(logger) << "took " << (g_get_monotonic_time () - time_start) / 1000000.0f << " seconds to init dee";
277 time_start = g_get_monotonic_time();
278
279@@ -103,7 +105,7 @@
280 std::vector<DeeModelIter*>::iterator it;
281 for (it = iters_.begin(); it != iters_.end(); it++)
282 {
283- unity::dash::Result* result = new unity::dash::Result(model_, (*it), NULL);
284+ unity::dash::Result* result = new unity::dash::Result(model_, (*it), tag);
285 result_view->AddResult (*result);
286 }
287