>> However, I replaced line 525 >> >> + free_cache([]) >> - gc >> - get_mem >> >> And I was not able to reproduce the problem. > > ah, good to know. thanks. This is due to a bug in booh-classifier; however, that bug doesn't explain the whole problem alone.. I've made some progress. I have come up with the following C example; before posting to gnome's bugzilla, I wanted to ask around if it does make sense? If you have a few minutes to spare -> http://pastebin.ca/1641693 #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <gtk/gtk.h> #include <dirent.h> void display_mem() { char buf[1024]; char *ptr, *ptr2; ssize_t amount; int fd = open("/proc/self/status", O_RDONLY); if (fd == -1) { printf("cannot open file\n"); return; } amount = read(fd, buf, 1023); buf[amount] = '\0'; if (!(ptr = strstr(buf, "VmRSS:"))) { printf("VmRSS not found in: %s\n", buf); close(fd); return; } if (!(ptr2 = strchr(ptr, '\n'))) { printf("\\n not found\n"); close(fd); return; } *(ptr2+1) = '\0'; printf(ptr); close(fd); } #define count 16 int main(int argc, char** argv) { GError *error = NULL; DIR *dir; struct dirent *dp; int i; GdkPixbuf* pixbufs[count] = { NULL, }; gtk_init(&argc, &argv); display_mem(); dir = opendir("."); if (dir == NULL) { fprintf(stderr, "opendir failed\n"); abort(); } i = 0; while ((dp = readdir (dir)) != NULL) { char* file = dp->d_name; if (!strstr(file, ".jpg")) continue; printf("Load %s\n", file); pixbufs[i] = gdk_pixbuf_new_from_file(file, &error); if (!pixbufs[i]) { fprintf(stderr, "failure loading %s: %s\n", file, error->message); abort(); } i++; if (i == count) { display_mem(); printf("Unref all but last\n"); for ( i = 0; i < count - 1; i++ ) g_object_unref(pixbufs[i]); display_mem(); // last one becomes first in array pixbufs[0] = pixbufs[count - 1]; i = 1; } } closedir (dir); return 0; } /* That tries to mimic the allocation/deallocation in a ruby-gnome2 program showing the jpg images in current directory; the mark&sweep GC of ruby won't allow for all GdkPixbufs to be unref'ed immediately after being not used anymore, but instead they are unref'ed grouped, all but last one because we want to keep the last pixbuf around for the program. Result (against 2.18.3) on x86_64 architecture: VmRSS: 5768 kB Load img_0290.jpg Load 1.jpg Load 2.jpg Load 3.jpg Load 4.jpg Load 10.jpg Load 11.jpg Load 12.jpg Load 13.jpg Load 14.jpg Load 15.jpg Load 16.jpg Load 17.jpg Load 18.jpg Load 19.jpg Load 20.jpg VmRSS: 380968 kB Unref all but last VmRSS: 29788 kB Load 21.jpg Load 22.jpg Load 23.jpg Load 24.jpg Load 25.jpg Load 26.jpg Load 27.jpg Load 28.jpg Load 29.jpg Load 30.jpg Load 31.jpg Load 32.jpg Load 33.jpg Load 34.jpg Load 35.jpg VmRSS: 380920 kB Unref all but last VmRSS: 357508 kB Load 36.jpg Load 37.jpg Load 38.jpg Load 39.jpg Load 40.jpg Load 41.jpg Load 42.jpg Load 43.jpg Load 44.jpg Load 45.jpg Load 46.jpg Load 47.jpg Load 48.jpg Load 49.jpg Load t.jpg VmRSS: 380916 kB Unref all but last VmRSS: 380916 kB Load t2.jpg Load t3.jpg Load 100.jpg Notice that after a few iterations, even after unref'ing all pixbufs but the last one, the RSS of the program is very high. Contrast with the same program on i686 architecture (with the same data): VmRSS: 4872 kB Load img_0290.jpg Load 1.jpg Load 2.jpg Load 3.jpg Load 4.jpg Load 10.jpg Load 11.jpg Load 12.jpg Load 13.jpg Load 14.jpg Load 15.jpg Load 16.jpg Load 17.jpg Load 18.jpg Load 19.jpg Load 20.jpg VmRSS: 380048 kB Unref all but last VmRSS: 28868 kB Load 21.jpg Load 22.jpg Load 23.jpg Load 24.jpg Load 25.jpg Load 26.jpg Load 27.jpg Load 28.jpg Load 29.jpg Load 30.jpg Load 31.jpg Load 32.jpg Load 33.jpg Load 34.jpg Load 35.jpg VmRSS: 380048 kB Unref all but last VmRSS: 28868 kB Load 36.jpg Load 37.jpg Load 38.jpg Load 39.jpg Load 40.jpg Load 41.jpg Load 42.jpg Load 43.jpg Load 44.jpg Load 45.jpg Load 46.jpg Load 47.jpg Load 48.jpg Load 49.jpg Load t.jpg VmRSS: 380048 kB Unref all but last VmRSS: 28868 kB Load t2.jpg Load t3.jpg Load 100.jpg On i686, the memory seems to be properly reclaimed, not on x86_64.. */ -- Guillaume Cottenceau - http://zarb.org/~gc/ -- Guillaume Cottenceau - http://zarb.org/~gc/
on 2009-10-24 19:00
on 2009-10-26 14:17
2009/10/24 Guillaume Cottenceau <gcottenc@gmail.com> > I've made some progress. I have come up with the following C example; > before posting to gnome's bugzilla, I wanted to ask around if it does > make sense? If you have a few minutes to spare -> > http://pastebin.ca/1641693 > > With the foloowing patch, it does not leak anymore on my debian sid 64. --- test-unref-orig.c 2009-10-26 14:09:28.550389546 +0100 +++ test-unref.c 2009-10-26 14:10:07.627736671 +0100 @@ -42,8 +42,10 @@ GError *error = NULL; DIR *dir; struct dirent *dp; - int i; + int i,j; + int last = count - 1; GdkPixbuf* pixbufs[count] = { NULL, }; + char* file; gtk_init(&argc, &argv); @@ -58,10 +60,10 @@ i = 0; while ((dp = readdir (dir)) != NULL) { - char* file = dp->d_name; - if (!strstr(file, ".jpg")) + file = dp->d_name; + if (!(strstr(file, ".jpg")||strstr(file, ".JPG"))) continue; - printf("Load %s\n", file); + // printf("Load %s\n", file); pixbufs[i] = gdk_pixbuf_new_from_file(file, &error); if (!pixbufs[i]) { fprintf(stderr, "failure loading %s: %s\n", @@ -70,13 +72,17 @@ } i++; if (i == count) { + printf("\nBefore unref\n"); display_mem(); printf("Unref all but last\n"); - for ( i = 0; i < count - 1; i++ ) - g_object_unref(pixbufs[i]); + for ( j = 0; j < last; j++ ) + g_object_unref(pixbufs[j]); display_mem(); // last one becomes first in array - pixbufs[0] = pixbufs[count - 1]; + pixbufs[0] = gdk_pixbuf_copy(pixbufs[last]); + g_object_unref(pixbufs[last]); + printf("After putting last in first place\n"); + display_mem(); i = 1; } } Apart from the cosmetic changes, the main difference is I copy the pifbux from last to first, instead of copying the pointer. I tried a lot of variants, and I suspect "gdk_pixbuf_new_from_file" is keeping some ref around until you clear all ref opened from the function. However my C skill are mostly inexistent, so it may well be something else. > On i686, the memory seems to be properly reclaimed, not on x86_64.. > I don't have a 32 bits system to test on right now, but I do see the problem on x86_64. Looks like a bug in GDK to me. regards Simon Arnaud
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.