comparison 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
comparison
equal deleted inserted replaced
5169:6c6d78781d59 5170:5ddbab03b0e6
175 Elemcount instances_on_free_list; 175 Elemcount instances_on_free_list;
176 Bytecount bytes_on_free_list; 176 Bytecount bytes_on_free_list;
177 Bytecount bytes_on_free_list_overhead; 177 Bytecount bytes_on_free_list_overhead;
178 #ifdef MEMORY_USAGE_STATS 178 #ifdef MEMORY_USAGE_STATS
179 Bytecount nonlisp_bytes_in_use; 179 Bytecount nonlisp_bytes_in_use;
180 Bytecount lisp_ancillary_bytes_in_use;
180 struct generic_usage_stats stats; 181 struct generic_usage_stats stats;
181 #endif 182 #endif
182 } lrecord_stats [countof (lrecord_implementations_table)]; 183 } lrecord_stats [countof (lrecord_implementations_table)];
183 184
184 #endif /* (not) NEW_GC */ 185 #endif /* (not) NEW_GC */
3886 int j; 3887 int j;
3887 for (j = 0; j < imp->num_extra_nonlisp_memusage_stats; j++) 3888 for (j = 0; j < imp->num_extra_nonlisp_memusage_stats; j++)
3888 lrecord_stats[i].nonlisp_bytes_in_use += 3889 lrecord_stats[i].nonlisp_bytes_in_use +=
3889 lrecord_stats[i].stats.othervals[j]; 3890 lrecord_stats[i].stats.othervals[j];
3890 } 3891 }
3892 if (imp && imp->num_extra_lisp_ancillary_memusage_stats)
3893 {
3894 int j;
3895 for (j = 0; j < imp->num_extra_lisp_ancillary_memusage_stats; j++)
3896 lrecord_stats[i].lisp_ancillary_bytes_in_use +=
3897 lrecord_stats[i].stats.othervals
3898 [j + imp->offset_lisp_ancillary_memusage_stats];
3899 }
3891 } 3900 }
3892 #endif /* defined (MEMORY_USAGE_STATS) && !defined (NEW_GC) */ 3901 #endif /* defined (MEMORY_USAGE_STATS) && !defined (NEW_GC) */
3893 } 3902 }
3894 3903
3895 #define COUNT_FROB_BLOCK_USAGE(type) \ 3904 #define COUNT_FROB_BLOCK_USAGE(type) \
4038 { 4047 {
4039 sprintf (buf, "%s-non-lisp-storage", name); 4048 sprintf (buf, "%s-non-lisp-storage", name);
4040 pl = gc_plist_hack (buf, lrecord_stats[i].nonlisp_bytes_in_use, 4049 pl = gc_plist_hack (buf, lrecord_stats[i].nonlisp_bytes_in_use,
4041 pl); 4050 pl);
4042 tgu_val += lrecord_stats[i].nonlisp_bytes_in_use; 4051 tgu_val += lrecord_stats[i].nonlisp_bytes_in_use;
4052 }
4053 if (lrecord_stats[i].lisp_ancillary_bytes_in_use)
4054 {
4055 sprintf (buf, "%s-lisp-ancillary-storage", name);
4056 pl = gc_plist_hack (buf, lrecord_stats[i].
4057 lisp_ancillary_bytes_in_use,
4058 pl);
4059 tgu_val += lrecord_stats[i].lisp_ancillary_bytes_in_use;
4043 } 4060 }
4044 #endif /* MEMORY_USAGE_STATS */ 4061 #endif /* MEMORY_USAGE_STATS */
4045 pluralize_and_append (buf, name, "-freed"); 4062 pluralize_and_append (buf, name, "-freed");
4046 if (lrecord_stats[i].instances_freed != 0) 4063 if (lrecord_stats[i].instances_freed != 0)
4047 pl = gc_plist_hack (buf, lrecord_stats[i].instances_freed, pl); 4064 pl = gc_plist_hack (buf, lrecord_stats[i].instances_freed, pl);
4173 { 4190 {
4174 struct generic_usage_stats gustats; 4191 struct generic_usage_stats gustats;
4175 struct usage_stats object_stats; 4192 struct usage_stats object_stats;
4176 int i; 4193 int i;
4177 Lisp_Object val = Qnil; 4194 Lisp_Object val = Qnil;
4178 Lisp_Object stats_list = OBJECT_PROPERTY (object, memusage_stats_list); 4195 Lisp_Object stats_list;
4196
4197 if (INTP (object) || CHARP (object))
4198 invalid_argument ("No memory associated with immediate objects (int or char)",
4199 object);
4200
4201 stats_list = OBJECT_PROPERTY (object, memusage_stats_list);
4179 4202
4180 xzero (object_stats); 4203 xzero (object_stats);
4181 lisp_object_storage_size (object, &object_stats); 4204 lisp_object_storage_size (object, &object_stats);
4182 4205
4183 val = acons (Qobject_actually_requested, 4206 val = acons (Qobject_actually_requested,
4221 } 4244 }
4222 4245
4223 return Fnreverse (val); 4246 return Fnreverse (val);
4224 } 4247 }
4225 4248
4249 /* Compute total memory usage associated with an object, including
4250
4251 (a) Storage (including overhead) allocated to the object itself
4252 (b) Storage (including overhead) for ancillary non-Lisp structures attached
4253 to the object
4254 (c) Storage (including overhead) for ancillary Lisp objects attached
4255 to the object
4256
4257 Store the three types of memory into the return values provided they
4258 aren't NULL, and return a sum of the three values. Also store the
4259 structure of individual statistics into STATS if non-zero.
4260
4261 Note that the value for type (c) is the sum of all three types of
4262 memory associated with the ancillary Lisp objects.
4263 */
4264
4265 Bytecount
4266 lisp_object_memory_usage_full (Lisp_Object object, Bytecount *storage_size,
4267 Bytecount *extra_nonlisp_storage,
4268 Bytecount *extra_lisp_ancillary_storage,
4269 struct generic_usage_stats *stats)
4270 {
4271 Bytecount total;
4272 struct lrecord_implementation *imp = XRECORD_LHEADER_IMPLEMENTATION (object);
4273
4274 total = lisp_object_storage_size (object, NULL);
4275 if (storage_size)
4276 *storage_size = total;
4277
4278 if (HAS_OBJECT_METH_P (object, memory_usage))
4279 {
4280 int i;
4281 struct generic_usage_stats gustats;
4282 Bytecount sum;
4283
4284 xzero (gustats);
4285 OBJECT_METH (object, memory_usage, (object, &gustats));
4286
4287 if (stats)
4288 *stats = gustats;
4289
4290 sum = 0;
4291 for (i = 0; i < imp->num_extra_nonlisp_memusage_stats; i++)
4292 sum += gustats.othervals[i];
4293 total += sum;
4294 if (extra_nonlisp_storage)
4295 *extra_nonlisp_storage = sum;
4296
4297 sum = 0;
4298 for (i = 0; i < imp->num_extra_lisp_ancillary_memusage_stats; i++)
4299 sum += gustats.othervals[imp->offset_lisp_ancillary_memusage_stats +
4300 i];
4301 total += sum;
4302 if (extra_lisp_ancillary_storage)
4303 *extra_lisp_ancillary_storage = sum;
4304 }
4305 else
4306 {
4307 if (extra_nonlisp_storage)
4308 *extra_nonlisp_storage = 0;
4309 if (extra_lisp_ancillary_storage)
4310 *extra_lisp_ancillary_storage = 0;
4311 }
4312
4313 return total;
4314 }
4315
4316
4317 Bytecount
4318 lisp_object_memory_usage (Lisp_Object object)
4319 {
4320 return lisp_object_memory_usage_full (object, NULL, NULL, NULL, NULL);
4321 }
4322
4226 #endif /* MEMORY_USAGE_STATS */ 4323 #endif /* MEMORY_USAGE_STATS */
4227 4324
4228 #ifdef ALLOC_TYPE_STATS 4325 #ifdef ALLOC_TYPE_STATS
4229 4326
4230 DEFUN ("total-object-memory-usage", Ftotal_object_memory_usage, 0, 0, 0, /* 4327 DEFUN ("total-object-memory-usage", Ftotal_object_memory_usage, 0, 0, 0, /*
4256 { 4353 {
4257 int i; 4354 int i;
4258 4355
4259 for (i = 0; i < countof (lrecord_implementations_table); i++) 4356 for (i = 0; i < countof (lrecord_implementations_table); i++)
4260 { 4357 {
4261 int len = 0;
4262 int nonlisp_len = 0;
4263 int seen_break = 0;
4264
4265 struct lrecord_implementation *imp = lrecord_implementations_table[i]; 4358 struct lrecord_implementation *imp = lrecord_implementations_table[i];
4266 4359
4267 if (!imp) 4360 if (!imp)
4268 continue; 4361 continue;
4269 /* For some of the early objects, Qnil was not yet initialized at 4362 /* For some of the early objects, Qnil was not yet initialized at
4270 the time of object initialization, so it came up as Qnull_pointer. 4363 the time of object initialization, so it came up as Qnull_pointer.
4271 Fix that now. */ 4364 Fix that now. */
4272 if (EQ (imp->memusage_stats_list, Qnull_pointer)) 4365 if (EQ (imp->memusage_stats_list, Qnull_pointer))
4273 imp->memusage_stats_list = Qnil; 4366 imp->memusage_stats_list = Qnil;
4274 { 4367 {
4368 Elemcount len = 0;
4369 Elemcount nonlisp_len = 0;
4370 Elemcount lisp_len = 0;
4371 Elemcount lisp_offset = 0;
4372 int group_num = 0;
4373 int slice_num = 0;
4374
4275 LIST_LOOP_2 (item, imp->memusage_stats_list) 4375 LIST_LOOP_2 (item, imp->memusage_stats_list)
4276 { 4376 {
4277 if (!NILP (item) && !EQ (item, Qt)) 4377 if (EQ (item, Qt))
4278 { 4378 {
4279 len++; 4379 group_num++;
4280 if (!seen_break) 4380 if (group_num == 1)
4281 nonlisp_len++; 4381 lisp_offset = len;
4382 slice_num = 0;
4383 }
4384 else if (EQ (item, Qnil))
4385 {
4386 slice_num++;
4282 } 4387 }
4283 else 4388 else
4284 seen_break++; 4389 {
4390 if (slice_num == 0)
4391 {
4392 if (group_num == 0)
4393 nonlisp_len++;
4394 else if (group_num == 1)
4395 lisp_len++;
4396 }
4397 len++;
4398 }
4285 } 4399 }
4400
4401 imp->num_extra_memusage_stats = len;
4402 imp->num_extra_nonlisp_memusage_stats = nonlisp_len;
4403 imp->num_extra_lisp_ancillary_memusage_stats = lisp_len;
4404 imp->offset_lisp_ancillary_memusage_stats = lisp_offset;
4286 } 4405 }
4287
4288 imp->num_extra_memusage_stats = len;
4289 imp->num_extra_nonlisp_memusage_stats = nonlisp_len;
4290 } 4406 }
4291 } 4407 }
4292 4408
4293 #endif /* MEMORY_USAGE_STATS */ 4409 #endif /* MEMORY_USAGE_STATS */
4294 4410