* Re: How to debug elisp memory leak
2004-09-16 14:45 How to debug elisp memory leak Frode Vatvedt Fjeld
@ 2004-09-17 18:14 ` Stefan Monnier
2004-09-20 12:23 ` Frode Vatvedt Fjeld
2004-10-03 12:53 ` Florian Weimer
1 sibling, 1 reply; 8+ messages in thread
From: Stefan Monnier @ 2004-09-17 18:14 UTC (permalink / raw)
> I'm regularly getting the "lisp pointer size exceeded" warning after
> about one week of running emacs. When this happens, nothing I do, such
> as killing buffers, seems to help much; at most I can postpone the
> inevitable crash for a few more minutes of work.
> I figure there's a memory leak; somewhere there's e.g a global
> variable with an ever-growing list of whatever. But I have no idea
> where to start looking for what or where this might be. Can anyone
> help me?
> I'm using GNU Emacs 21.3.1, but this behavior has been consistent for
> at least a few months and minor versions of Emacs.
I don't think there's a quick answer to this.
But for a start, can you try the pckage below?
It provides a command M-x memory-usage which will show what Emacs's heap is
made of (whic proportion is cons cells, buffer text, strings, arrays, ...).
It's not much info, but it's a start: when you get the "lisp pointer size
exceeded" thingy, hit M-x memory-usage and post the result here.
Also, try then to kill (lots of or even all) buffers and re-run M-x
memory-usage and post that result as well.
Stefan
PS: Better to hit M-x memory-usage at least once before to make sure it
works and is already loaded and ready to be used.
;;; memory-usage.el --- Analyze the memory usage of Emacs in various ways
;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@cs.yale.edu>
;; Keywords: maint
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;
;;; Code:
(defun buffer-size-bytes (b)
"Return total number of bytes in the buffer contents."
(with-current-buffer b
(save-restriction
(widen)
(- (position-bytes (point-max)) (position-bytes (point-min))))))
(defun buffer-gap-bytes (b)
"Return total number of bytes in the buffer gap."
(with-current-buffer b
(gap-size)))
(defun buffer-total-bytes (b)
"Return total number of ralloc bytes used by buffer."
(with-current-buffer b
(save-restriction
(widen)
(+ (position-bytes (point-max))
(- (position-bytes (point-min)))
(gap-size)))))
;;;###autoload
(defun memory-usage ()
"List all buffers and their memory usage."
(interactive)
(pop-to-buffer (get-buffer-create "*Buffer Details*"))
(erase-buffer)
(let* ((bufs (buffer-list))
(num (length bufs))
(gc-stats (garbage-collect))
(conses (nth 0 gc-stats))
(symbols (nth 1 gc-stats))
(markers (nth 2 gc-stats))
(strings (nth 3 gc-stats))
(vectors (nth 4 gc-stats))
(floats (nth 5 gc-stats))
(intervals (nth 6 gc-stats)))
(insert (format "Garbage collection stats:\n%s\n\n =>" gc-stats))
(insert (format "\t%d bytes in cons cells\n" (* 8 (+ (car conses) (cdr conses)))))
(insert (format "\t%d bytes in symbols\n" (* 24 (+ (car symbols) (cdr symbols)))))
(insert (format "\t%d bytes in markers\n" (* 20 (+ (car markers) (cdr markers)))))
(insert (format "\t%d bytes of string chars\n" strings))
(insert (format "\t%d bytes of vector slots\n" (* 4 vectors)))
(insert (format "\t%d bytes in floats\n" (* 12 (+ (car floats) (cdr floats)))))
(insert (format "\t%d bytes in intervals\n" (* 28 (+ (car intervals) (cdr intervals)))))
(insert (format "\nTotal bytes in lisp objects (not counting string and vector headers): %d\n\n"
(+ (* 8 (+ (car conses) (cdr conses)))
(* 24 (+ (car symbols) (cdr symbols)))
(* 20 (+ (car markers) (cdr markers)))
strings
vectors
(* 12 (+ (car floats) (cdr floats)))
(* 28 (+ (car intervals) (cdr intervals))))))
(insert (format "Buffer ralloc memory usage:\n%d buffers\n%d bytes total (%d in gaps)\n"
num
(apply #'+ (mapcar #'buffer-total-bytes bufs))
(apply #'+ (mapcar #'buffer-gap-bytes bufs))))
(insert (format "%10s\t%s\t%s\n\n" "Size" "Gap" "Name"))
(insert (mapconcat
(lambda (b)
(format "%10d\t%s\t%s"
(buffer-size-bytes b)
(buffer-gap-bytes b)
(buffer-name b)))
(sort bufs (lambda (b1 b2)
(> (buffer-size-bytes b1) (buffer-size-bytes b2))))
"\n"))
(insert "\n"))
(goto-char (point-min)))
(provide 'memory-usage)
;; arch-tag: 04e012f0-3c59-4319-8d1a-e86204671ec5
;;; memory-usage.el ends here
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: How to debug elisp memory leak
2004-09-16 14:45 How to debug elisp memory leak Frode Vatvedt Fjeld
2004-09-17 18:14 ` Stefan Monnier
@ 2004-10-03 12:53 ` Florian Weimer
1 sibling, 0 replies; 8+ messages in thread
From: Florian Weimer @ 2004-10-03 12:53 UTC (permalink / raw)
* Frode Vatvedt Fjeld:
> I'm using GNU Emacs 21.3.1, but this behavior has been consistent for
> at least a few months and minor versions of emacs.
Recently, a memory leak in decode-coding-region (and other code that
uses some internal routines of coding.c) has been discovered. It is
fixed in CVS (by Kenichi Handa). I'm using the patch below for
version 21.3.
diff -urNad /home/fw/debian/tmp/emacs21-21.3+1/src/callproc.c emacs21-21.3+1/src/callproc.c
--- /home/fw/debian/tmp/emacs21-21.3+1/src/callproc.c 2002-07-09 02:02:36.000000000 +0200
+++ emacs21-21.3+1/src/callproc.c 2004-09-30 09:44:42.000000000 +0200
@@ -790,6 +790,8 @@
{
detect_coding (&process_coding, bufptr, nread);
if (process_coding.composing != COMPOSITION_DISABLED)
+ /* We have not yet allocated the composition
+ data because the coding type was undecided. */
coding_allocate_composition_data (&process_coding, PT);
}
if (process_coding.cmp_data)
diff -urNad /home/fw/debian/tmp/emacs21-21.3+1/src/coding.c emacs21-21.3+1/src/coding.c
--- /home/fw/debian/tmp/emacs21-21.3+1/src/coding.c 2003-03-16 23:06:55.000000000 +0100
+++ emacs21-21.3+1/src/coding.c 2004-09-30 09:44:42.000000000 +0200
@@ -5489,8 +5489,11 @@
coding_allocate_composition_data (coding, from);
}
- /* Try to skip the heading and tailing ASCIIs. */
- if (coding->type != coding_type_ccl)
+ /* Try to skip the heading and tailing ASCIIs. We can't skip them
+ if we must run CCL program or there are compositions to
+ encode. */
+ if (coding->type != coding_type_ccl
+ && (! coding->cmp_data || coding->cmp_data->used == 0))
{
int from_byte_orig = from_byte, to_byte_orig = to_byte;
@@ -5506,6 +5509,7 @@
if (!replace)
/* We must record and adjust for this new text now. */
adjust_after_insert (from, from_byte_orig, to, to_byte_orig, len);
+ coding_free_composition_data (coding);
return 0;
}
@@ -6106,12 +6110,16 @@
coding_save_composition (coding, from, to, str);
/* Try to skip the heading and tailing ASCIIs. */
- if (coding->type != coding_type_ccl)
+ if (coding->type != coding_type_ccl
+ && (! coding->cmp_data || coding->cmp_data->used == 0))
{
SHRINK_CONVERSION_REGION (&from, &to_byte, coding, XSTRING (str)->data,
1);
if (from == to_byte)
- return (nocopy ? str : Fcopy_sequence (str));
+ {
+ coding_free_composition_data (coding);
+ return (nocopy ? str : Fcopy_sequence (str));
+ }
shrinked_bytes = from + (STRING_BYTES (XSTRING (str)) - to_byte);
}
diff -urNad /home/fw/debian/tmp/emacs21-21.3+1/src/fileio.c emacs21-21.3+1/src/fileio.c
--- /home/fw/debian/tmp/emacs21-21.3+1/src/fileio.c 2003-02-04 11:52:40.000000000 +0100
+++ emacs21-21.3+1/src/fileio.c 2004-09-30 09:44:42.000000000 +0200
@@ -4087,7 +4087,7 @@
if (how_much < 0)
{
xfree (conversion_buffer);
-
+ coding_free_composition_data (&coding);
if (how_much == -1)
error ("IO error reading %s: %s",
XSTRING (orig_filename)->data, emacs_strerror (errno));
@@ -4109,6 +4109,7 @@
if (bufpos == inserted)
{
xfree (conversion_buffer);
+ coding_free_composition_data (&coding);
emacs_close (fd);
specpdl_ptr--;
/* Truncate the buffer to the size of the file. */
diff -urNad /home/fw/debian/tmp/emacs21-21.3+1/src/process.c emacs21-21.3+1/src/process.c
--- /home/fw/debian/tmp/emacs21-21.3+1/src/process.c 2003-03-16 23:06:56.000000000 +0100
+++ emacs21-21.3+1/src/process.c 2004-09-30 09:44:42.000000000 +0200
@@ -3347,6 +3347,7 @@
object = XPROCESS (proc)->encoding_buf;
encode_coding (coding, (char *) buf, XSTRING (object)->data,
len, STRING_BYTES (XSTRING (object)));
+ coding_free_composition_data (coding);
len = coding->produced;
buf = XSTRING (object)->data;
if (temp_buf)
^ permalink raw reply [flat|nested] 8+ messages in thread