Merge lp:~unity-team/unity/pixbufcache-fixes into lp:unity

Proposed by Mikkel Kamstrup Erlandsen
Status: Merged
Merged at revision: 491
Proposed branch: lp:~unity-team/unity/pixbufcache-fixes
Merge into: lp:unity
Diff against target: 226 lines (+37/-76)
1 file modified
unity/unity-pixbuf-cache.vala (+37/-76)
To merge this branch: bzr merge lp:~unity-team/unity/pixbufcache-fixes
Reviewer Review Type Date Requested Status
Unity Team Pending
Review via email: mp+34981@code.launchpad.net

Description of the change

While this branch does not fix the big leak we have when bringing up a place, it fixes a leak of maybe 5-10mb we'll have on startup and it drastically improves the loading/rendering times of icons in the places:

Fix a big leak when loading pixbufs with Unity.PixbufCache

Optimize IO when loading pixbufs, by using a bigger buffer

Remove a few unnecessary async calls to reduce the number of mainloop round trips

Remove some stale outcommented code

To post a comment you must log in.

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-02 23:10:22 +0000
3+++ unity/unity-pixbuf-cache.vala 2010-09-09 14:21:44 +0000
4@@ -152,9 +152,9 @@
5 return queue.size != 0;
6 }
7
8- public async void set_image_from_icon_name (Ctk.Image image,
9- string icon_name,
10- int size)
11+ public void set_image_from_icon_name (Ctk.Image image,
12+ string icon_name,
13+ int size)
14 {
15 var key = hash_template.printf (icon_name, size);
16 Pixbuf? ret = cache[key];
17@@ -177,21 +177,20 @@
18 queue_timeout = Idle.add (load_iteration);
19 }
20
21- public async void set_image_from_icon_name_real (Ctk.Image image,
22- string icon_name,
23- int size)
24+ private async void set_image_from_icon_name_real (Ctk.Image image,
25+ string icon_name,
26+ int size)
27 {
28 var key = hash_template.printf (icon_name, size);
29 Pixbuf? ret = cache[key];
30
31+ /* We need a secondary cache check because the icon may have
32+ * been cached while we where waiting in the queue */
33 if (ret is Pixbuf)
34 {
35 image.set_from_pixbuf (ret);
36 return;
37 }
38-
39- Idle.add (set_image_from_icon_name_real.callback);
40- yield;
41
42 if (ret == null)
43 {
44@@ -200,7 +199,7 @@
45 if (info != null)
46 {
47 var filename = info.get_filename ();
48- ret = yield load_from_filepath (filename, size, image, key);
49+ ret = yield load_from_filepath (filename, size);
50 }
51
52 if (ret is Pixbuf)
53@@ -219,7 +218,7 @@
54 }
55 }
56
57- public async void set_image_from_gicon_string (Ctk.Image image,
58+ public void set_image_from_gicon_string (Ctk.Image image,
59 string data,
60 int size)
61 {
62@@ -244,28 +243,27 @@
63 queue_timeout = Idle.add (load_iteration);
64 }
65
66- public async void set_image_from_gicon_string_real (Ctk.Image image,
67- string gicon_as_string,
68- int size)
69+ private async void set_image_from_gicon_string_real (Ctk.Image image,
70+ string gicon_as_string,
71+ int size)
72 {
73 var key = hash_template.printf (gicon_as_string, size);
74 Pixbuf? ret = cache[key];
75
76+ /* We need a secondary cache check because the icon may have
77+ * been cached while we where waiting in the queue */
78 if (ret is Pixbuf)
79 {
80 image.set_from_pixbuf (ret);
81 return;
82 }
83-
84- Idle.add (set_image_from_gicon_string_real.callback);
85- yield;
86-
87+
88 if (ret == null)
89 {
90 if (gicon_as_string[0] == '/')
91 {
92 try {
93- ret = yield load_from_filepath (gicon_as_string, size, image, key);
94+ ret = yield load_from_filepath (gicon_as_string, size);
95 } catch (Error err) {
96 message (@"Unable to load $gicon_as_string as file: %s",
97 err.message);
98@@ -281,7 +279,7 @@
99 {
100 var filename = info.get_filename ();
101
102- ret = yield load_from_filepath (filename, size, image, key);
103+ ret = yield load_from_filepath (filename, size);
104 }
105
106 if (ret == null)
107@@ -293,7 +291,7 @@
108 */
109 if (gicon_as_string.has_suffix (".png")
110 || gicon_as_string.has_suffix (".xpm")
111- || gicon_as_string.has_suffix (".gir")
112+ || gicon_as_string.has_suffix (".gif")
113 || gicon_as_string.has_suffix (".jpg"))
114 {
115 string real_name = gicon_as_string[0:gicon_as_string.length-4];
116@@ -301,7 +299,7 @@
117 if (info != null)
118 {
119 var fname = info.get_filename ();
120- ret = yield load_from_filepath (fname, size, image, key);
121+ ret = yield load_from_filepath (fname, size);
122 }
123 }
124 }
125@@ -330,30 +328,41 @@
126 set_image_from_gicon_string (image, icon.to_string (), size);
127 }
128
129- public async Gdk.Pixbuf? load_from_filepath (string filename, int size, Ctk.Image? image=null, string key)
130+ public async Gdk.Pixbuf? load_from_filepath (string filename, int size)
131 {
132
133 if (filename != null)
134 {
135 File datafile = File.new_for_path (filename);
136+ FileInfo info = yield datafile.query_info_async (
137+ FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
138+ FileQueryInfoFlags.NONE,
139+ Priority.LOW);
140+ string mimetype = info.get_content_type ();
141+
142 try
143 {
144 var stream = yield datafile.read_async (Priority.DEFAULT, null);
145
146 if (stream is FileInputStream)
147 {
148- uchar[] buf = new uchar[16];
149+ /* TODO: Tweak buf size to optimize io */
150+ uchar[] buf = new uchar[1024];
151 void *data;
152 size_t data_size;
153- yield IO.read_stream_async (stream, buf, 16, Priority.DEFAULT,
154-
155+ yield IO.read_stream_async (stream, buf, buf.length, Priority.DEFAULT,
156 null, out data, out data_size);
157- string sdata = ((string)data).ndup(data_size);
158
159- var loader = new Gdk.PixbufLoader ();
160+ /* Construct a loader for a given mimetype so it doesn't
161+ * have to do expensive second guesssing */
162+ var loader = new Gdk.PixbufLoader.with_mime_type(mimetype);
163 loader.write ((uchar[])data, data_size);
164 loader.close ();
165
166+ /* We must manually free the data block allocated by
167+ * IO.read_stream_async */
168+ g_free (data);
169+
170 return loader.get_pixbuf ();
171 }
172 }
173@@ -366,53 +375,5 @@
174 return null;
175 }
176
177- /*
178- private async void load_from_file_async (Ctk.Image i,
179- string f,
180- int s,
181- string k)
182- {
183- unowned Ctk.Image image = i;
184- string filename = f;
185- int size = s;
186- string key = k;
187-
188- if (filename != null)
189- {
190- File datafile = File.new_for_path (filename);
191- try
192- {
193- var stream = yield datafile.read_async (Priority.DEFAULT, null);
194-
195- if (stream is FileInputStream)
196- {
197- uchar[] buf = new uchar[16];
198- void *data;
199- size_t data_size;
200- yield IO.read_stream_async (stream, buf, 16, Priority.DEFAULT,
201-
202- null, out data, out data_size);
203- string sdata = ((string)data).ndup(data_size);
204-
205- var loader = new Gdk.PixbufLoader ();
206- loader.write ((uchar[])data, data_size);
207- loader.close ();
208-
209- image.set_from_pixbuf (loader.get_pixbuf ());
210-
211- cache[key] = loader.get_pixbuf ();
212- }
213- }
214- catch (Error ee)
215- {
216- warning ("Unable to load image file '%s': %s", filename, ee.message);
217- }
218- }
219- }
220- */
221-
222- /*
223- * Private Methods
224- */
225 }
226 }