Has anyone tried throwing DTrace at this problem? I don't have any Solaris access here at RubyConf, and I don't use FCGI, or I'd give it a go. On 10/15/05, Yohanes Santoso <ysantoso-rubytalk / dessyku.is-a-geek.org> wrote: > Eric Mahurin <eric_mahurin / yahoo.com> writes: > > > n=2**13;(1..n).each{|i| > > a=(1..i).to_a;self.class.send(:define_method,:"f#{i}"){i*i}};GC.start; > > IO.readlines("/proc/#{Process.pid}/status").grep(/VmSize/).display' > > VmSize: 172028 kB > > > ruby -e ' > > n=2**13;(1..n).each{|i| > > a=(1..i).to_a;self.class.send(:define_method,:"f#{i}"){i*i};a=nil};GC.start; > > IO.readlines("/proc/#{Process.pid}/status").grep(/VmSize/).display' > > VmSize: 11504 kB > > Stop right there. I want to remind people that you can't use VmSize as > a leak indicator. In some OS, VmSize is an always increasing > number. Memory allocated in a process is not returned to the OS until > the process dies. > > Here is a C program that free() every malloc(), yet still have > outrageous VmSize; > > ysantoso@jenny:/tmp$ gcc -W -Wall ./leak.c -o leak && ./leak immed && ./leak not_immed > Freeing immediately > ----BEFORE---- > malloc count = 0 > free count = 0 > VmSize: 1572 kB > VmLck: 0 kB > VmRSS: 364 kB > VmData: 156 kB > VmStk: 88 kB > VmExe: 4 kB > VmLib: 1280 kB > VmPTE: 16 kB > Executing leak test > unwinding > ----AFTER----- > malloc count = 8193 > free count = 8193 > VmSize: 1572 kB > VmLck: 0 kB > VmRSS: 440 kB > VmData: 156 kB > VmStk: 88 kB > VmExe: 4 kB > VmLib: 1280 kB > VmPTE: 16 kB > Not freeing immediately > ----BEFORE---- > malloc count = 0 > free count = 0 > VmSize: 1568 kB > VmLck: 0 kB > VmRSS: 364 kB > VmData: 156 kB > VmStk: 84 kB > VmExe: 4 kB > VmLib: 1280 kB > VmPTE: 16 kB > Executing leak test > unwinding > freeing 8192 elements > ----AFTER----- > malloc count = 8193 > free count = 8192 > VmSize: 206360 kB > VmLck: 0 kB > VmRSS: 205280 kB > VmData: 204948 kB > VmStk: 84 kB > VmExe: 4 kB > VmLib: 1280 kB > VmPTE: 216 kB > ysantoso@jenny:/tmp$ cat ./leak.c > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > > int malloc_count = 0; > int free_count = 0; > > void * > counting_malloc(size_t size) > { > malloc_count++; > return malloc(size); > } > > void > counting_free(void *ptr) > { > free_count++; > if (ptr == NULL) { > fprintf(stderr, "Warning: free-ing NULL pointer\n"); > } > free(ptr); > } > > void > display_vminfo() > { > FILE *status = fopen("/proc/self/status", "r"); > char line[132]; > while (fgets(line, 132, status)) { > if (strstr(line, "Vm") == line) { > printf(line); > } > } > fclose(status); > } > > /* allocs about 200M of mem. if free_immed_p, then memory allocated is free()ed immediately */ > void > leak_test(int free_immed_p) > { > int i, j; > char **array = NULL; > int max_array_idx = -1; > int max_array_size = 8192; > int element_size = 25*1024; > array = counting_malloc(max_array_size * sizeof(char*)); > if (!array) { > fprintf(stderr, "Unable to malloc\n"); > goto die; > } > for (i=0; i < max_array_size; i++) { > char *element = counting_malloc(element_size); > if (!element) { > fprintf(stderr, "Unable to malloc\n"); > goto die; > } > /* walk through the allocated mem to negate any lazy allocation schema */ > for (j=0; j < element_size; j++) { > element[j] = '\0'; > } > array[i] = element; > max_array_idx = i; > if (free_immed_p) { > counting_free(element); > } > } > die: > fprintf(stderr, "unwinding\n"); > if (array) { > if (!free_immed_p) { > fprintf(stderr, "freeing %d elements\n", max_array_idx + 1); > for (i=0; i < max_array_idx; i++) { > counting_free(array[i]); > } > } > counting_free(array); > } > } > > > > void > usage() > { > fprintf(stderr, "Don't understand argument. immed or not_immed\n"); > } > > int > main(int argc, char **argv) > { > int free_immed_p; > if (argc != 2) { > usage(); > return 1; > } > if (strcmp("immed", argv[1]) == 0) { > printf("Freeing immediately\n"); > free_immed_p = 1; > } else if (strcmp("not_immed", argv[1]) == 0) { > printf("Not freeing immediately\n"); > free_immed_p = 0; > } else { > usage(); > return 1; > } > printf("----BEFORE----\n"); > printf("malloc count = %d\n", malloc_count); > printf("free count = %d\n", free_count); > display_vminfo(); > printf("Executing leak test\n"); > leak_test(free_immed_p); > printf("----AFTER-----\n"); > printf("malloc count = %d\n", malloc_count); > printf("free count = %d\n", free_count); > display_vminfo(); > return 0; > } > > > > > Here is the fixed version: > > You can't say this if you only have VmSize. > > > YS. > >