GNOME Bugzilla – Bug 158962
Reduce memory usage of load_themes
Last modified: 2004-12-22 21:47:04 UTC
Today, load_themes in gtkiconthreme.c allocates alot of memory per instance. Here is some of the dumps I got from valgrind: ==26850== 93996 bytes in 3894 blocks are still reachable in loss record 7474 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x71D208: g_strdup (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5D8A: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA45A1: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA4DDA: gtk_icon_theme_has_icon (in /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0x5CCBF58: gnome_icon_lookup (in /usr/lib/libgnomeui-2.so.0.600.0) ==26850== ==26850== ==26850== 93996 bytes in 3894 blocks are still reachable in loss record 7475 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x71D208: g_strdup (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5D8A: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA45A1: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA48BD: gtk_icon_theme_lookup_icon (in /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0x5CCDD80: gnome_icon_theme_lookup_icon (in /usr/lib/libgnomeui-2.so.0.600.0) ==26850== ==26850== ==26850== 99328 bytes in 97 blocks are still reachable in loss record 7476 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x70F6D3: g_mem_chunk_alloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x6FE8C9: (within /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x6FDEC1: g_hash_table_replace (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5DCD: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA45A1: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== 118378 bytes in 6148 blocks are still reachable in loss record 7478 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x71D208: g_strdup (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5D8A: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA458C: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA48BD: gtk_icon_theme_lookup_icon (in /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0x5CCDD80: gnome_icon_theme_lookup_icon (in /usr/lib/libgnomeui-2.so.0.600.0) ==26850== ==26850== ==26850== 118378 bytes in 6148 blocks are still reachable in loss record 7479 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x71D208: g_strdup (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5D8A: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA458C: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA4DDA: gtk_icon_theme_has_icon (in /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0x5CCBF58: gnome_icon_lookup (in /usr/lib/libgnomeui-2.so.0.600.0) ==26850== ==26850== ==26850== 156672 bytes in 153 blocks are still reachable in loss record 7480 of 7480 ==26850== at 0x3414A2A8: malloc (vg_replace_malloc.c:131) ==26850== by 0x70E526: g_malloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x70F6D3: g_mem_chunk_alloc (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x6FE8C9: (within /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0x6FDEC1: g_hash_table_replace (in /usr/lib/libglib-2.0.so.0.400.0) ==26850== by 0xAA5DCD: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA6042: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA43B3: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA458C: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) ==26850== by 0xAA47F9: (within /usr/lib/libgtk-x11-2.0.so.0.400.0) The list goes on and on. I am running on Fedora Core 2. I think part of the problem is that RedHat creates lots of excess symlinks in their icons folder: [benm@omega Bluecurve]$ pwd /usr/share/icons/Bluecurve [benm@omega Bluecurve]$ find -name \*.png | wc -l 5348 However, Gtk+ should be designed for this type of usage. I have two ideas to reduce usage here: (Easy) 1) Split the name that we store into file and directory components, and then share common strings. Right now, this string is stored for each icon: abs_file = g_build_filename (dir, file, NULL); So, in the bluecurve theme with 5k icons, the following string: /usr/share/icons/Bluecurve is duplicated for each icon. This is over 100kb!!!! So, what should be done is for each icon to store in different strings: * The folder name (eg, /usr/share/icons/Bluecurve/24x24/apps/) * the file name (gnome-terminal.png) Both strings will likely be duplicated, so we should share the common strings here. How much memory would this save, well today what we have uses: [benm@omega icons]$ find Bluecurve -name "*.png" -printf "`pwd`/%p\n" | wc -c 321917 So about 321 kb for the bluecurve folder. The new method would use [benm@omega icons]$ find Bluecurve -name "*.png" -printf "`pwd`/%h\n" | sort | uniq | wc -c 1501 1.5 kb for the directory [benm@omega icons]$ find Bluecurve -name "*.png" -printf "%f\n" | sort | uniq | wc -c 27707 27 kb for the file names. So that is 28.5 kb rather than 321 kb! (Hard) 2) Create a cache which could be mmap'd and thus shared across processes The hard way to do this would be to have some sort of binary format that multiple processes could mmap in order to look up icon information. So basically, someone would ahve to create this cache and put it somewhere in the home directory. It would contain a read-only hashtable which could be used to look up icon information. Every process would mmap these caches into memory and use them to look things up. Advantages: - the cost of the ghashtable is shared across every process. Thats a few 100 kb according to valgrind, so multiply that by 10 or 20 apps that might use it, gives you a fairly big savings - Could be used along with the string reduction method - Reduced startup time
This has been addressed in GTK+ HEAD. *** This bug has been marked as a duplicate of 154034 ***