Merge lp:~unity-team/unity/mmaped-icons into lp:unity

Proposed by Mikkel Kamstrup Erlandsen on 2010-10-05
Status: Merged
Approved by: Neil J. Patel on 2010-12-01
Approved revision: 569
Merge reported by: Mikkel Kamstrup Erlandsen
Merged at revision: not available
Proposed branch: lp:~unity-team/unity/mmaped-icons
Merge into: lp:unity
Diff against target: 171 lines (+34/-51)
1 file modified
unity/unity-pixbuf-cache.vala (+34/-51)
To merge this branch: bzr merge lp:~unity-team/unity/mmaped-icons
Reviewer Review Type Date Requested Status
Neil J. Patel (community) 2010-10-05 Approve on 2010-12-01
Review via email: mp+37634@code.launchpad.net

Description of the Change

Improves speed and system load of icon loading by making use of Gtk+'s mmap()ed icon-theme.cache. It also batches the loads into clusters of 10 icons.

While this doesn't completely fix the rendering speed of the places on a cold cache, it is definitely a step in the right direction.

To post a comment you must log in.
Neil J. Patel (njpatel) wrote :

Looks good, and works (testing on a maverick install). Feel free to merge into 0.2 series. Also, is it worth asking didrocks to SRU?

review: Approve

Branch was merged into lp:unity/0.2. Launchpad is unable to reflect that change. Sorry.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'unity/unity-pixbuf-cache.vala'
2--- unity/unity-pixbuf-cache.vala 2010-09-22 09:55:24 +0000
3+++ unity/unity-pixbuf-cache.vala 2010-10-05 16:24:42 +0000
4@@ -126,15 +126,18 @@
5 cache.clear ();
6 }
7
8- private async void process_icon_queue_async ()
9+ /* Do the actual work of loading icons.
10+ * IMPORTANT: Must be run with G_PRIORITY_LOW in order to allow Clutter
11+ * and other libs to have time on the mainloop. Like syncing
12+ * to vblank to have smooth rendering */
13+ private bool process_icon_queue_real ()
14 {
15- /* Hardcoded numbers make gord cry - but so be it - we are taking
16- * a second guess of the inode size here, for the better of mankind */
17- uchar[] buf = new uchar[4096];
18+ PixbufCacheTask task;
19+ int batch_size = 10;
20 int count = 0;
21- var timer = new Timer ();
22- PixbufCacheTask task;
23
24+ /* Load in batches of 10 (choosen by fair dice rool - honest!),
25+ * then yield the mainloop */
26 while ((task = queue.poll()) != null)
27 {
28 if (task.image is Ctk.Image)
29@@ -142,53 +145,50 @@
30 switch (task.type)
31 {
32 case PixbufRequestType.ICON_NAME:
33- yield set_image_from_icon_name_real (task, buf, buf.length);
34+ set_image_from_icon_name_real (task);
35 break;
36 case PixbufRequestType.GICON_STRING:
37- yield set_image_from_gicon_string_real (task, buf, buf.length);
38+ set_image_from_gicon_string_real (task);
39 break;
40 default:
41 critical ("Internal error. Unknown PixbufRequestType: %u",
42 task.type);
43 break;
44 }
45- }
46+ }
47+
48 count++;
49+ if (count >= batch_size)
50+ {
51+ /* Yield the mainloop for a bit more than 1 frame
52+ * so we can draw the new icons */
53+ Timeout.add (1000/Clutter.get_default_frame_rate() + 5,
54+ process_icon_queue_real);
55+ return false;
56+ }
57+
58 }
59-
60- timer.stop ();
61- debug ("Loaded %i icons in %fms", count, timer.elapsed()*1000);
62
63 /* Queue depleted */
64 queue_source = 0;
65+ return false;
66 }
67
68 private void process_icon_queue ()
69 {
70 if (queue_source == 0)
71 {
72- /* queue_source is set to 0 by process_icon_queue_async()
73+ /* queue_source is set to 0 by process_icon_queue_real()
74 * when the queue is depleted.
75 * It's important that we dispatch in an idle call here since
76 * it gives clients a chance to queue more icons before we
77- * hammer the IO */
78- queue_source = Idle.add (dispatch_process_icon_queue_async);
79+ * hammer the IO.
80+ * MUCHO IMPORTANTE: We want G_PRIORITY_LOW in order to not steal the
81+ * mainloop from Clutter and friends */
82+ queue_source = Idle.add_full (Priority.LOW,
83+ process_icon_queue_real);
84 }
85 }
86-
87- private bool dispatch_process_icon_queue_async ()
88- {
89- /* Run three processings in "parallel". While we are not multithreaded,
90- * it still makes sense to do since one branch may be waiting in
91- * 'yield' for async IO, while the other can be parsing image data.
92- * The number of parallel workers has been chosen by best perceived
93- * responsiveness for bringing up the Applications place */
94- process_icon_queue_async.begin ();
95- process_icon_queue_async.begin ();
96- process_icon_queue_async.begin ();
97-
98- return false;
99- }
100
101 /**
102 * If the icon is already cached then set it immediately on @image. Otherwise
103@@ -224,9 +224,7 @@
104 process_icon_queue ();
105 }
106
107- private async void set_image_from_icon_name_real (PixbufCacheTask task,
108- void* buf,
109- size_t buf_length)
110+ private void set_image_from_icon_name_real (PixbufCacheTask task)
111 {
112 Pixbuf? ret = cache[task.key];
113
114@@ -242,8 +240,7 @@
115 var info = theme.lookup_icon (task.data, task.size, 0);
116 if (info != null)
117 {
118- var filename = info.get_filename ();
119- ret = yield load_from_filepath (filename, task.size, buf, buf_length);
120+ ret = info.load_icon ();
121 }
122
123 if (ret is Pixbuf)
124@@ -295,9 +292,7 @@
125 process_icon_queue ();
126 }
127
128- private async void set_image_from_gicon_string_real (PixbufCacheTask task,
129- void* buf,
130- size_t buf_length)
131+ private void set_image_from_gicon_string_real (PixbufCacheTask task)
132 {
133 Pixbuf? ret = cache[task.key];
134
135@@ -309,16 +304,6 @@
136 return;
137 }
138
139- if (task.data[0] == '/')
140- {
141- try {
142- ret = yield load_from_filepath (task.data, task.size, buf, buf_length);
143- } catch (Error err) {
144- message (@"Unable to load $(task.data) as file: %s",
145- err.message);
146- }
147- }
148-
149 if (ret == null)
150 {
151 try {
152@@ -326,8 +311,7 @@
153 var info = theme.lookup_by_gicon (icon, task.size, 0);
154 if (info != null)
155 {
156- var filename = info.get_filename ();
157- ret = yield load_from_filepath (filename, task.size, buf, buf_length);
158+ ret = info.load_icon ();
159 }
160
161 if (ret == null)
162@@ -346,8 +330,7 @@
163 info = theme.lookup_icon (real_name, task.size, 0);
164 if (info != null)
165 {
166- var fname = info.get_filename ();
167- ret = yield load_from_filepath (fname, task.size, buf, buf_length);
168+ ret = info.load_icon ();
169 }
170 }
171 }