=== modified file 'lisp/emacs-lisp/chart.el' --- lisp/emacs-lisp/chart.el 2012-05-13 03:05:06 +0000 +++ lisp/emacs-lisp/chart.el 2012-07-17 13:00:22 +0000 @@ -676,23 +676,25 @@ "Chart the current storage requirements of Emacs." (interactive) (let* ((data (garbage-collect)) - (names '("strings/2" "vectors" - "conses" "free cons" - "syms" "free syms" - "markers" "free mark" - ;; "floats" "free flt" - )) - (nums (list (/ (nth 3 data) 2) - (nth 4 data) - (car (car data)) ; conses - (cdr (car data)) - (car (nth 1 data)) ; syms - (cdr (nth 1 data)) - (car (nth 2 data)) ; markers - (cdr (nth 2 data)) - ;(car (nth 5 data)) ; floats are Emacs only - ;(cdr (nth 5 data)) - ))) + (cons-info (nth 0 data)) + (symbol-info (nth 1 data)) + (misc-info (nth 2 data)) + (string-info (nth 3 data)) + (vector-info (nth 4 data)) + (float-info (nth 5 data)) + (interval-info (nth 6 data)) + (buffer-info (nth 7 data)) + (names '("conses" "symbols" "miscs" "strings" + "vectors" "floats" "intervals" "buffers")) + (nums (list (* (nth 1 cons-info) (nth 2 cons-info)) + (* (nth 1 symbol-info) (nth 2 symbol-info)) + (* (nth 1 misc-info) (nth 2 misc-info)) + (+ (* (nth 1 string-info) (nth 2 string-info)) + (nth 3 string-info)) + (nth 3 vector-info) + (* (nth 1 float-info) (nth 2 float-info)) + (* (nth 1 interval-info) (nth 2 interval-info)) + (* (nth 1 buffer-info) (nth 2 buffer-info))))) ;; Let's create the chart! (chart-bar-quickie 'vertical "Emacs Runtime Storage Usage" names "Storage Items" === modified file 'src/alloc.c' --- src/alloc.c 2012-07-17 12:31:29 +0000 +++ src/alloc.c 2012-07-17 13:37:24 +0000 @@ -187,11 +187,24 @@ int abort_on_gc; -/* Number of live and free conses etc. */ - -static EMACS_INT total_conses, total_markers, total_symbols, total_vector_size; -static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; -static EMACS_INT total_free_floats, total_floats, total_free_vector_bytes; +/* Number of live and free objects of the particular type. */ + +static EMACS_INT total_conses, total_free_conses; +static EMACS_INT total_symbols, total_free_symbols; +static EMACS_INT total_miscs, total_free_miscs; +static EMACS_INT total_intervals, total_free_intervals; +static EMACS_INT total_floats, total_free_floats; +static EMACS_INT total_buffers; + +/* Number of live strings, number of bytes + used by them, number of free strings. */ + +static EMACS_INT total_strings, total_string_bytes, total_free_strings; + +/* Number of live vectors, amount of bytes used by + them, number of free bytes in vector blocks. */ + +static EMACS_INT total_vectors, total_vector_bytes, total_free_vector_bytes; /* Points to memory space allocated as "spare", to be freed if we run out of memory. We keep one large block, four cons-blocks, and @@ -1478,10 +1491,6 @@ static int interval_block_index = INTERVAL_BLOCK_SIZE; -/* Number of free and live intervals. */ - -static EMACS_INT total_free_intervals, total_intervals; - /* List of free intervals. */ static INTERVAL interval_free_list; @@ -1521,6 +1530,7 @@ consing_since_gc += sizeof (struct interval); intervals_consed++; + total_intervals++; total_free_intervals--; RESET_INTERVAL (val); val->gcmarkbit = 0; @@ -1702,14 +1712,6 @@ static struct Lisp_String *string_free_list; -/* Number of live and free Lisp_Strings. */ - -static EMACS_INT total_strings, total_free_strings; - -/* Number of bytes used by live strings. */ - -static EMACS_INT total_string_size; - /* Given a pointer to a Lisp_String S which is on the free-list string_free_list, return a pointer to its successor in the free-list. */ @@ -1939,9 +1941,9 @@ MALLOC_UNBLOCK_INPUT; - --total_free_strings; - ++total_strings; - ++strings_consed; + total_free_strings--; + total_strings++; + strings_consed++; consing_since_gc += sizeof *s; #ifdef GC_CHECK_STRING_BYTES @@ -2067,6 +2069,7 @@ old_data->string = NULL; } + total_string_bytes += needed; consing_since_gc += needed; } @@ -2080,8 +2083,7 @@ struct string_block *live_blocks = NULL; string_free_list = NULL; - total_strings = total_free_strings = 0; - total_string_size = 0; + total_strings = total_free_strings = total_string_bytes = 0; /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ for (b = string_blocks; b; b = next) @@ -2107,7 +2109,7 @@ UNMARK_BALANCE_INTERVALS (s->intervals); ++total_strings; - total_string_size += STRING_BYTES (s); + total_string_bytes += STRING_BYTES (s); } else { @@ -2636,6 +2638,7 @@ eassert (!FLOAT_MARKED_P (XFLOAT (val))); consing_since_gc += sizeof (struct Lisp_Float); floats_consed++; + total_floats++; total_free_floats--; return val; } @@ -2744,6 +2747,7 @@ XSETCDR (val, cdr); eassert (!CONS_MARKED_P (XCONS (val))); consing_since_gc += sizeof (struct Lisp_Cons); + total_conses++; total_free_conses--; cons_cells_consed++; return val; @@ -3069,6 +3073,14 @@ ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ : vector->header.next.nbytes) +/* Return the memory footprint of vector V in bytes. + Do not use for pseudovectors since the most of them + has something beyond Lisp objects at the beginning. */ + +#define VECTOR_BYTES(v) \ + (eassert (!((v)->header.size & PSEUDOVECTOR_FLAG)), \ + (header_size + VECTOR_SIZE (v) * word_size)) + /* Reclaim space used by unmarked vectors. */ static void @@ -3077,7 +3089,7 @@ struct vector_block *block = vector_blocks, **bprev = &vector_blocks; struct Lisp_Vector *vector, *next, **vprev = &large_vectors; - total_free_vector_bytes = total_vector_size = 0; + total_vectors = total_free_vector_bytes = total_vector_bytes = 0; memset (vector_free_lists, 0, sizeof (vector_free_lists)); /* Looking through vector blocks. */ @@ -3092,7 +3104,8 @@ if (VECTOR_MARKED_P (vector)) { VECTOR_UNMARK (vector); - total_vector_size += VECTOR_SIZE (vector); + total_vectors++; + total_vector_bytes += vector->header.next.nbytes; next = ADVANCE (vector, vector->header.next.nbytes); } else @@ -3148,7 +3161,10 @@ if (VECTOR_MARKED_P (vector)) { VECTOR_UNMARK (vector); - total_vector_size += VECTOR_SIZE (vector); + total_vectors++; + /* This code assumes that all pseudovectors are + small enough to be allocated from blocks. */ + total_vector_bytes += VECTOR_BYTES (vector); vprev = &vector->header.next.vector; } else @@ -3198,7 +3214,8 @@ /* Back to a reasonable maximum of mmap'ed areas. */ mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif - + total_vectors++; + total_vector_bytes += nbytes; consing_since_gc += nbytes; vector_cells_consed += len; } @@ -3248,6 +3265,7 @@ XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) - header_size) / word_size); + total_buffers++; /* Note that the fields of B are not initialized. */ return b; } @@ -3492,6 +3510,7 @@ p->declared_special = 0; consing_since_gc += sizeof (struct Lisp_Symbol); symbols_consed++; + total_symbols++; total_free_symbols--; return val; } @@ -3499,7 +3518,7 @@ /*********************************************************************** - Marker (Misc) Allocation + Misc Objects Allocation ***********************************************************************/ /* Like union Lisp_Misc, but padded so that its size is a multiple of @@ -3517,20 +3536,20 @@ /* Allocation of markers and other objects that share that structure. Works like allocation of conses. */ -#define MARKER_BLOCK_SIZE \ - ((1020 - sizeof (struct marker_block *)) / sizeof (union aligned_Lisp_Misc)) +#define MISC_BLOCK_SIZE \ + ((1020 - sizeof (struct misc_block *)) / sizeof (union aligned_Lisp_Misc)) -struct marker_block +struct misc_block { - /* Place `markers' first, to preserve alignment. */ - union aligned_Lisp_Misc markers[MARKER_BLOCK_SIZE]; - struct marker_block *next; + /* Place `miscs' first, to preserve alignment. */ + union aligned_Lisp_Misc miscs[MISC_BLOCK_SIZE]; + struct misc_block *next; }; -static struct marker_block *marker_block; -static int marker_block_index = MARKER_BLOCK_SIZE; +static struct misc_block *misc_block; +static int misc_block_index = MISC_BLOCK_SIZE; -static union Lisp_Misc *marker_free_list; +static union Lisp_Misc *misc_free_list; /* Return a newly allocated Lisp_Misc object, with no substructure. */ @@ -3543,28 +3562,29 @@ MALLOC_BLOCK_INPUT; - if (marker_free_list) + if (misc_free_list) { - XSETMISC (val, marker_free_list); - marker_free_list = marker_free_list->u_free.chain; + XSETMISC (val, misc_free_list); + misc_free_list = misc_free_list->u_free.chain; } else { - if (marker_block_index == MARKER_BLOCK_SIZE) + if (misc_block_index == MISC_BLOCK_SIZE) { - struct marker_block *new = lisp_malloc (sizeof *new, MEM_TYPE_MISC); - new->next = marker_block; - marker_block = new; - marker_block_index = 0; - total_free_markers += MARKER_BLOCK_SIZE; + struct misc_block *new = lisp_malloc (sizeof *new, MEM_TYPE_MISC); + new->next = misc_block; + misc_block = new; + misc_block_index = 0; + total_free_miscs += MISC_BLOCK_SIZE; } - XSETMISC (val, &marker_block->markers[marker_block_index].m); - marker_block_index++; + XSETMISC (val, &misc_block->miscs[misc_block_index].m); + misc_block_index++; } MALLOC_UNBLOCK_INPUT; - --total_free_markers; + total_miscs++; + total_free_miscs--; consing_since_gc += sizeof (union Lisp_Misc); misc_objects_consed++; XMISCANY (val)->gcmarkbit = 0; @@ -3577,10 +3597,9 @@ free_misc (Lisp_Object misc) { XMISCTYPE (misc) = Lisp_Misc_Free; - XMISC (misc)->u_free.chain = marker_free_list; - marker_free_list = XMISC (misc); - - total_free_markers++; + XMISC (misc)->u_free.chain = misc_free_list; + misc_free_list = XMISC (misc); + total_free_miscs++; } /* Return a Lisp_Misc_Save_Value object containing POINTER and @@ -4309,17 +4328,17 @@ { if (m->type == MEM_TYPE_MISC) { - struct marker_block *b = (struct marker_block *) m->start; - ptrdiff_t offset = (char *) p - (char *) &b->markers[0]; + struct misc_block *b = (struct misc_block *) m->start; + ptrdiff_t offset = (char *) p - (char *) &b->miscs[0]; /* P must point to the start of a Lisp_Misc, not be one of the unused cells in the current misc block, and not be on the free-list. */ return (offset >= 0 - && offset % sizeof b->markers[0] == 0 - && offset < (MARKER_BLOCK_SIZE * sizeof b->markers[0]) - && (b != marker_block - || offset / sizeof b->markers[0] < marker_block_index) + && offset % sizeof b->miscs[0] == 0 + && offset < (MISC_BLOCK_SIZE * sizeof b->miscs[0]) + && (b != misc_block + || offset / sizeof b->miscs[0] < misc_block_index) && ((union Lisp_Misc *) p)->u_any.type != Lisp_Misc_Free); } else @@ -5345,10 +5364,14 @@ Garbage collection happens automatically if you cons more than `gc-cons-threshold' bytes of Lisp data since previous garbage collection. `garbage-collect' normally returns a list with info on amount of space in use: - ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) - (USED-MISCS . FREE-MISCS) USED-STRING-CHARS USED-VECTOR-SLOTS - (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS) - (USED-STRINGS . FREE-STRINGS)) + ((CONS INTERNAL-SIZE USED-CONSES FREE-CONSES) + (SYMBOL INTERNAL-SIZE USED-SYMBOLS FREE-SYMBOLS) + (MISC INTERNAL-SIZE USED-MISCS FREE-MISCS) + (STRING INTERNAL-SIZE USED-STRINGS USED-STRING-BYTES FREE-STRING) + (VECTOR INTERNAL-SIZE USED-VECTORS USED-VECTOR-BYTES FREE-VECTOR-BYTES) + (FLOAT INTERNAL-SIZE USED-FLOATS FREE-FLOATS) + (INTERVAL INTERNAL-SIZE USED-INTERVALS FREE-INTERVALS) + (BUFFER INTERNAL-SIZE USED-BUFFERS)) However, if there was overflow in pure space, `garbage-collect' returns nil, because real GC can't be done. See Info node `(elisp)Garbage Collection'. */) @@ -5594,9 +5617,9 @@ tot += total_conses * sizeof (struct Lisp_Cons); tot += total_symbols * sizeof (struct Lisp_Symbol); - tot += total_markers * sizeof (union Lisp_Misc); - tot += total_string_size; - tot += total_vector_size * sizeof (Lisp_Object); + tot += total_miscs * sizeof (union Lisp_Misc); + tot += total_string_bytes; + tot += total_vector_bytes; tot += total_floats * sizeof (struct Lisp_Float); tot += total_intervals * sizeof (struct interval); tot += total_strings * sizeof (struct Lisp_String); @@ -5621,20 +5644,38 @@ unbind_to (count, Qnil); - total[0] = Fcons (make_number (total_conses), + total[0] = list4 (Qcons, make_number (sizeof (struct Lisp_Cons)), + make_number (total_conses), make_number (total_free_conses)); - total[1] = Fcons (make_number (total_symbols), + + total[1] = list4 (Qsymbol, make_number (sizeof (struct Lisp_Symbol)), + make_number (total_symbols), make_number (total_free_symbols)); - total[2] = Fcons (make_number (total_markers), - make_number (total_free_markers)); - total[3] = make_number (total_string_size); - total[4] = make_number (total_vector_size); - total[5] = Fcons (make_number (total_floats), + + total[2] = list4 (Qmisc, make_number (sizeof (union Lisp_Misc)), + make_number (total_miscs), + make_number (total_free_miscs)); + + total[3] = list5 (Qstring, make_number (sizeof (struct Lisp_String)), + make_number (total_strings), + make_number (total_string_bytes), + make_number (total_free_strings)); + + total[4] = list5 (Qvector, make_number (sizeof (struct Lisp_Vector)), + make_number (total_vectors), + make_number (total_vector_bytes), + make_number (total_free_vector_bytes)); + + total[5] = list4 (Qfloat, make_number (sizeof (struct Lisp_Float)), + make_number (total_floats), make_number (total_free_floats)); - total[6] = Fcons (make_number (total_intervals), + + total[6] = list4 (Qinterval, make_number (sizeof (struct interval)), + make_number (total_intervals), make_number (total_free_intervals)); - total[7] = Fcons (make_number (total_strings), - make_number (total_free_strings)); + + total[7] = list3 (Qbuffer, make_number (sizeof (struct buffer)), + make_number (total_buffers)); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES { @@ -6477,47 +6518,47 @@ /* Put all unmarked misc's on free list. For a marker, first unchain it from the buffer it points into. */ { - register struct marker_block *mblk; - struct marker_block **mprev = &marker_block; - register int lim = marker_block_index; + register struct misc_block *mblk; + struct misc_block **mprev = &misc_block; + register int lim = misc_block_index; EMACS_INT num_free = 0, num_used = 0; - marker_free_list = 0; + misc_free_list = 0; - for (mblk = marker_block; mblk; mblk = *mprev) + for (mblk = misc_block; mblk; mblk = *mprev) { register int i; int this_free = 0; for (i = 0; i < lim; i++) { - if (!mblk->markers[i].m.u_any.gcmarkbit) + if (!mblk->miscs[i].m.u_any.gcmarkbit) { - if (mblk->markers[i].m.u_any.type == Lisp_Misc_Marker) - unchain_marker (&mblk->markers[i].m.u_marker); + if (mblk->miscs[i].m.u_any.type == Lisp_Misc_Marker) + unchain_marker (&mblk->miscs[i].m.u_marker); /* Set the type of the freed object to Lisp_Misc_Free. We could leave the type alone, since nobody checks it, but this might catch bugs faster. */ - mblk->markers[i].m.u_marker.type = Lisp_Misc_Free; - mblk->markers[i].m.u_free.chain = marker_free_list; - marker_free_list = &mblk->markers[i].m; + mblk->miscs[i].m.u_marker.type = Lisp_Misc_Free; + mblk->miscs[i].m.u_free.chain = misc_free_list; + misc_free_list = &mblk->miscs[i].m; this_free++; } else { num_used++; - mblk->markers[i].m.u_any.gcmarkbit = 0; + mblk->miscs[i].m.u_any.gcmarkbit = 0; } } - lim = MARKER_BLOCK_SIZE; + lim = MISC_BLOCK_SIZE; /* If this block contains only free markers and we have already seen more than two blocks worth of free markers then deallocate this block. */ - if (this_free == MARKER_BLOCK_SIZE && num_free > MARKER_BLOCK_SIZE) + if (this_free == MISC_BLOCK_SIZE && num_free > MISC_BLOCK_SIZE) { *mprev = mblk->next; /* Unhook from the free list. */ - marker_free_list = mblk->markers[0].m.u_free.chain; + misc_free_list = mblk->miscs[0].m.u_free.chain; lisp_free (mblk); } else @@ -6527,14 +6568,15 @@ } } - total_markers = num_used; - total_free_markers = num_free; + total_miscs = num_used; + total_free_miscs = num_free; } /* Free all unmarked buffers */ { register struct buffer *buffer = all_buffers, *prev = 0, *next; + total_buffers = 0; while (buffer) if (!VECTOR_MARKED_P (buffer)) { @@ -6548,6 +6590,7 @@ } else { + total_buffers++; VECTOR_UNMARK (buffer); UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); prev = buffer, buffer = buffer->header.next.buffer; @@ -6595,7 +6638,7 @@ data[0] = make_number (min (MOST_POSITIVE_FIXNUM, (total_free_conses * sizeof (struct Lisp_Cons) - + total_free_markers * sizeof (union Lisp_Misc) + + total_free_miscs * sizeof (union Lisp_Misc) + total_free_symbols * sizeof (struct Lisp_Symbol) + total_free_floats * sizeof (struct Lisp_Float) + total_free_intervals * sizeof (struct interval) @@ -6605,7 +6648,7 @@ data[1] = make_number (min (MOST_POSITIVE_FIXNUM, mallinfo ().fordblks / 1024)); #else - data[1] = make_number (0); + data[1] = Qnil; #endif return Flist (2, data); } === modified file 'src/data.c' --- src/data.c 2012-07-10 08:43:46 +0000 +++ src/data.c 2012-07-17 12:36:31 +0000 @@ -83,12 +83,12 @@ Lisp_Object Qfloatp; Lisp_Object Qnumberp, Qnumber_or_marker_p; -Lisp_Object Qinteger; -static Lisp_Object Qsymbol, Qstring, Qcons, Qmarker, Qoverlay; +Lisp_Object Qinteger, Qinterval, Qfloat, Qvector; +Lisp_Object Qsymbol, Qstring, Qcons, Qmarker, Qmisc; Lisp_Object Qwindow; -static Lisp_Object Qfloat, Qwindow_configuration; +static Lisp_Object Qoverlay, Qwindow_configuration; static Lisp_Object Qprocess; -static Lisp_Object Qcompiled_function, Qframe, Qvector; +static Lisp_Object Qcompiled_function, Qframe; Lisp_Object Qbuffer; static Lisp_Object Qchar_table, Qbool_vector, Qhash_table; static Lisp_Object Qsubrp, Qmany, Qunevalled; @@ -3083,7 +3083,6 @@ DEFSYM (Qwindow_configuration, "window-configuration"); DEFSYM (Qprocess, "process"); DEFSYM (Qwindow, "window"); - /* DEFSYM (Qsubr, "subr"); */ DEFSYM (Qcompiled_function, "compiled-function"); DEFSYM (Qbuffer, "buffer"); DEFSYM (Qframe, "frame"); @@ -3091,6 +3090,9 @@ DEFSYM (Qchar_table, "char-table"); DEFSYM (Qbool_vector, "bool-vector"); DEFSYM (Qhash_table, "hash-table"); + /* Used by Fgarbage_collect. */ + DEFSYM (Qinterval, "interval"); + DEFSYM (Qmisc, "misc"); DEFSYM (Qdefun, "defun"); === modified file 'src/lisp.h' --- src/lisp.h 2012-07-16 04:47:31 +0000 +++ src/lisp.h 2012-07-17 12:36:31 +0000 @@ -2332,7 +2332,8 @@ extern Lisp_Object Qfloatp; extern Lisp_Object Qnumberp, Qnumber_or_marker_p; -extern Lisp_Object Qinteger; +extern Lisp_Object Qinteger, Qcons, Qsymbol, Qmarker, Qstring; +extern Lisp_Object Qmisc, Qvector, Qfloat, Qinterval, Qbuffer; extern Lisp_Object Qfont_spec, Qfont_entity, Qfont_object;