Mercurial > hg > xemacs-beta
diff src/alloc.c @ 5170:5ddbab03b0e6
various fixes to memory-usage stats
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2010-03-25 Ben Wing <ben@xemacs.org>
* diagnose.el (show-memory-usage):
* diagnose.el (show-object-memory-usage-stats):
Further changes to correspond with changes in the C code;
add an additional column in show-object-memory-usage-stats showing
the ancillary Lisp overhead used with each type; shrink columns for
windows in show-memory-usage to get it to fit in 79 chars.
src/ChangeLog addition:
2010-03-25 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (struct):
* alloc.c (finish_object_memory_usage_stats):
* alloc.c (object_memory_usage_stats):
* alloc.c (Fobject_memory_usage):
* alloc.c (lisp_object_memory_usage_full):
* alloc.c (compute_memusage_stats_length):
* lrecord.h:
* lrecord.h (struct lrecord_implementation):
Add fields to the `lrecord_implementation' structure to list an
offset into the array of extra statistics in a
`struct generic_usage_stats' and a length, listing the first slice
of ancillary Lisp-object memory. Compute automatically in
compute_memusage_stats_length(). Use to add an entry
`FOO-lisp-ancillary-storage' for object type FOO.
Don't crash when an int or char is given to object-memory-usage,
signal an error instead.
Add functions lisp_object_memory_usage_full() and
lisp_object_memory_usage() to compute the total memory usage of an
object (sum of object, non-Lisp attached, and Lisp ancillary
memory).
* array.c:
* array.c (gap_array_memory_usage):
* array.h:
Add function to return memory usage of a gap array.
* buffer.c (struct buffer_stats):
* buffer.c (compute_buffer_usage):
* buffer.c (vars_of_buffer):
* extents.c (compute_buffer_extent_usage):
* marker.c:
* marker.c (compute_buffer_marker_usage):
* extents.h:
* lisp.h:
Remove `struct usage_stats' arg from compute_buffer_marker_usage()
and compute_buffer_extent_usage() -- these are ancillary Lisp
objects and don't get accumulated into `struct usage_stats';
change the value of `memusage_stats_list' so that `markers' and
`extents' memory is in Lisp-ancillary, where it belongs.
In compute_buffer_marker_usage(), use lisp_object_memory_usage()
rather than lisp_object_storage_size().
* casetab.c:
* casetab.c (case_table_memory_usage):
* casetab.c (vars_of_casetab):
* emacs.c (main_1):
Add memory usage stats for case tables.
* lisp.h:
Add comment explaining the `struct generic_usage_stats' more,
as well as the new fields in lrecord_implementation.
* console-impl.h:
* console-impl.h (struct console_methods):
* scrollbar-gtk.c:
* scrollbar-gtk.c (gtk_compute_scrollbar_instance_usage):
* scrollbar-msw.c:
* scrollbar-msw.c (mswindows_compute_scrollbar_instance_usage):
* scrollbar-x.c:
* scrollbar-x.c (x_compute_scrollbar_instance_usage):
* scrollbar.c:
* scrollbar.c (struct scrollbar_instance_stats):
* scrollbar.c (compute_all_scrollbar_instance_usage):
* scrollbar.c (scrollbar_instance_memory_usage):
* scrollbar.c (scrollbar_objects_create):
* scrollbar.c (vars_of_scrollbar):
* scrollbar.h:
* symsinit.h:
* window.c:
* window.c (find_window_mirror_maybe):
* window.c (struct window_mirror_stats):
* window.c (compute_window_mirror_usage):
* window.c (window_mirror_memory_usage):
* window.c (compute_window_usage):
* window.c (window_objects_create):
* window.c (syms_of_window):
* window.c (vars_of_window):
Redo memory-usage associated with windows, window mirrors, and
scrollbar instances. Should fix crash in find_window_mirror,
among other things. Properly assign memo ry to object memory,
non-Lisp extra memory, and Lisp ancillary memory. For example,
redisplay structures are non-Lisp memory hanging off a window
mirror, not a window; make it an ancillary Lisp-object field.
Window mirrors and scrollbar instances have their own statistics,
among other things.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Thu, 25 Mar 2010 06:07:25 -0500 |
parents | e374ea766cc1 |
children | be6e5ea38dda |
line wrap: on
line diff
--- a/src/alloc.c Wed Mar 24 01:22:51 2010 -0500 +++ b/src/alloc.c Thu Mar 25 06:07:25 2010 -0500 @@ -177,6 +177,7 @@ Bytecount bytes_on_free_list_overhead; #ifdef MEMORY_USAGE_STATS Bytecount nonlisp_bytes_in_use; + Bytecount lisp_ancillary_bytes_in_use; struct generic_usage_stats stats; #endif } lrecord_stats [countof (lrecord_implementations_table)]; @@ -3888,6 +3889,14 @@ lrecord_stats[i].nonlisp_bytes_in_use += lrecord_stats[i].stats.othervals[j]; } + if (imp && imp->num_extra_lisp_ancillary_memusage_stats) + { + int j; + for (j = 0; j < imp->num_extra_lisp_ancillary_memusage_stats; j++) + lrecord_stats[i].lisp_ancillary_bytes_in_use += + lrecord_stats[i].stats.othervals + [j + imp->offset_lisp_ancillary_memusage_stats]; + } } #endif /* defined (MEMORY_USAGE_STATS) && !defined (NEW_GC) */ } @@ -4041,6 +4050,14 @@ pl); tgu_val += lrecord_stats[i].nonlisp_bytes_in_use; } + if (lrecord_stats[i].lisp_ancillary_bytes_in_use) + { + sprintf (buf, "%s-lisp-ancillary-storage", name); + pl = gc_plist_hack (buf, lrecord_stats[i]. + lisp_ancillary_bytes_in_use, + pl); + tgu_val += lrecord_stats[i].lisp_ancillary_bytes_in_use; + } #endif /* MEMORY_USAGE_STATS */ pluralize_and_append (buf, name, "-freed"); if (lrecord_stats[i].instances_freed != 0) @@ -4175,7 +4192,13 @@ struct usage_stats object_stats; int i; Lisp_Object val = Qnil; - Lisp_Object stats_list = OBJECT_PROPERTY (object, memusage_stats_list); + Lisp_Object stats_list; + + if (INTP (object) || CHARP (object)) + invalid_argument ("No memory associated with immediate objects (int or char)", + object); + + stats_list = OBJECT_PROPERTY (object, memusage_stats_list); xzero (object_stats); lisp_object_storage_size (object, &object_stats); @@ -4223,6 +4246,80 @@ return Fnreverse (val); } +/* Compute total memory usage associated with an object, including + + (a) Storage (including overhead) allocated to the object itself + (b) Storage (including overhead) for ancillary non-Lisp structures attached + to the object + (c) Storage (including overhead) for ancillary Lisp objects attached + to the object + + Store the three types of memory into the return values provided they + aren't NULL, and return a sum of the three values. Also store the + structure of individual statistics into STATS if non-zero. + + Note that the value for type (c) is the sum of all three types of + memory associated with the ancillary Lisp objects. +*/ + +Bytecount +lisp_object_memory_usage_full (Lisp_Object object, Bytecount *storage_size, + Bytecount *extra_nonlisp_storage, + Bytecount *extra_lisp_ancillary_storage, + struct generic_usage_stats *stats) +{ + Bytecount total; + struct lrecord_implementation *imp = XRECORD_LHEADER_IMPLEMENTATION (object); + + total = lisp_object_storage_size (object, NULL); + if (storage_size) + *storage_size = total; + + if (HAS_OBJECT_METH_P (object, memory_usage)) + { + int i; + struct generic_usage_stats gustats; + Bytecount sum; + + xzero (gustats); + OBJECT_METH (object, memory_usage, (object, &gustats)); + + if (stats) + *stats = gustats; + + sum = 0; + for (i = 0; i < imp->num_extra_nonlisp_memusage_stats; i++) + sum += gustats.othervals[i]; + total += sum; + if (extra_nonlisp_storage) + *extra_nonlisp_storage = sum; + + sum = 0; + for (i = 0; i < imp->num_extra_lisp_ancillary_memusage_stats; i++) + sum += gustats.othervals[imp->offset_lisp_ancillary_memusage_stats + + i]; + total += sum; + if (extra_lisp_ancillary_storage) + *extra_lisp_ancillary_storage = sum; + } + else + { + if (extra_nonlisp_storage) + *extra_nonlisp_storage = 0; + if (extra_lisp_ancillary_storage) + *extra_lisp_ancillary_storage = 0; + } + + return total; +} + + +Bytecount +lisp_object_memory_usage (Lisp_Object object) +{ + return lisp_object_memory_usage_full (object, NULL, NULL, NULL, NULL); +} + #endif /* MEMORY_USAGE_STATS */ #ifdef ALLOC_TYPE_STATS @@ -4258,10 +4355,6 @@ for (i = 0; i < countof (lrecord_implementations_table); i++) { - int len = 0; - int nonlisp_len = 0; - int seen_break = 0; - struct lrecord_implementation *imp = lrecord_implementations_table[i]; if (!imp) @@ -4272,21 +4365,44 @@ if (EQ (imp->memusage_stats_list, Qnull_pointer)) imp->memusage_stats_list = Qnil; { + Elemcount len = 0; + Elemcount nonlisp_len = 0; + Elemcount lisp_len = 0; + Elemcount lisp_offset = 0; + int group_num = 0; + int slice_num = 0; + LIST_LOOP_2 (item, imp->memusage_stats_list) { - if (!NILP (item) && !EQ (item, Qt)) + if (EQ (item, Qt)) { - len++; - if (!seen_break) - nonlisp_len++; + group_num++; + if (group_num == 1) + lisp_offset = len; + slice_num = 0; + } + else if (EQ (item, Qnil)) + { + slice_num++; } else - seen_break++; + { + if (slice_num == 0) + { + if (group_num == 0) + nonlisp_len++; + else if (group_num == 1) + lisp_len++; + } + len++; + } } + + imp->num_extra_memusage_stats = len; + imp->num_extra_nonlisp_memusage_stats = nonlisp_len; + imp->num_extra_lisp_ancillary_memusage_stats = lisp_len; + imp->offset_lisp_ancillary_memusage_stats = lisp_offset; } - - imp->num_extra_memusage_stats = len; - imp->num_extra_nonlisp_memusage_stats = nonlisp_len; } }