]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/memory-usage/memory-usage.el
* debbugs-gnu.el (debbugs-gnu-usertags): Rename argument to USERS
[gnu-emacs-elpa] / packages / memory-usage / memory-usage.el
index 7786035cd8e8e04c7517d79a7fa9c51740656e13..6e3749ddc7139a9d12d785c2cd46e230f317a67d 100644 (file)
   (setq n (* n memory-usage-word-size))
   (cons (* n (car c)) (* n (cdr c))))
 
+(defun memory-usage-format (bytes)
+  (setq bytes (/ bytes 1024.0))
+  (let ((units '(;; "B"
+                 "kB" "MB" "GB" "TB")))
+    (while (>= bytes 1024)
+      (setq bytes (/ bytes 1024.0))
+      (setq units (cdr units)))
+    (cond
+     ;; ((integerp bytes) (format "%4d%s" bytes (car units)))
+     ((>= bytes 100) (format "%4.0f%s" bytes (car units)))
+     ((>= bytes 10) (format "%4.1f%s" bytes (car units)))
+     (t (format "%4.2f%s" bytes (car units))))))
+
 ;;;###autoload
 (defun memory-usage ()
   "List all buffers and their memory usage."
   (let* ((bufs (buffer-list))
         (num (length bufs))
         (gc-stats (garbage-collect))
-        (conses    (memory-usage-mult-cons 2 (nth 0 gc-stats)))
-        (symbols   (memory-usage-mult-cons 6 (nth 1 gc-stats)))
-        (markers   (memory-usage-mult-cons 5 (nth 2 gc-stats)))
-        (chars     (nth 3 gc-stats))
-        (vectors   (nth 4 gc-stats))
-        (floats    (memory-usage-mult-cons 2 (nth 5 gc-stats)))
-        (intervals (memory-usage-mult-cons 7 (nth 6 gc-stats)))
-         (strings   (memory-usage-mult-cons 4 (nth 7 gc-stats))))
+         (gc-stats (if (numberp (caar gc-stats))
+                       (mapcar (lambda (x)
+                                 `(,(car x)
+                                   ,(max (* memory-usage-word-size (cadr x))
+                                         1)
+                                   ,@(let ((stat (nth (cddr x) gc-stats)))
+                                       (if (consp stat)
+                                           (list (car stat) (cdr stat))
+                                         (list stat)))))
+                               '((cons 2 . 0)
+                                 (symbol 6 . 1)
+                                 (marker 5 . 2)
+                                 (string 4 . 7)
+                                 (string-byte 0 . 3)
+                                 (vector-slot 1 . 4)
+                                 (float 2 . 5)
+                                 (interval 7 . 6)))
+                     gc-stats)))
     (insert (format "Garbage collection stats:\n%s\n\n =>" gc-stats))
-    (insert (format "\t%d+%d bytes in cons cells\n" (car conses) (cdr conses)))
-    (insert (format "\t%d+%d bytes in symbols\n" (car symbols) (cdr symbols)))
-    (insert (format "\t%d+%d bytes in markers\n" (car markers) (cdr markers)))
-    (insert (format "\t%d+%d bytes in floats\n" (car floats) (cdr floats)))
-    (insert (format "\t%d+%d bytes in intervals\n"
-                    (car intervals) (cdr intervals)))
-    (insert (format "\t%d+%d bytes in string headers\n"
-                    (car strings) (cdr strings)))
-    (insert (format "\t%d bytes of string chars\n" chars))
-    (insert (format "\t%d bytes of vector slots\n" vectors))
-    (let ((live (+ (car conses)
-                   (car symbols)
-                   (car markers)
-                   (car floats)
-                   (car intervals)
-                   (car strings)
-                   chars
-                  vectors))
-          (dead (+ (cdr conses)
-                   (cdr symbols)
-                   (cdr markers)
-                   (cdr floats)
-                   (cdr intervals)
-                   (cdr strings))))
-
-      (insert (format "\nTotal bytes in lisp objects: %d (live %d, dead %d)\n\n"
-                      (+ dead live) live dead)))
-
-    (insert (format "Buffer ralloc memory usage:\n%d buffers\n%d bytes total (%d in gaps)\n"
-                   num
-                   (apply #'+ (mapcar #'memory-usage-buffer-total-bytes bufs))
-                   (apply #'+ (mapcar #'memory-usage-buffer-gap-bytes bufs))))
+    (let ((live 0)
+          (dead 0))
+      (dolist (x gc-stats)
+        (let* ((size (nth 1 x))
+               (xlive (* size (nth 2 x)))
+               (xdead (if (nth 3 x) (* size (nth 3 x)))))
+          (insert (if xdead
+                      (format "\t%s (+ %s dead) in %s\n"
+                              (memory-usage-format xlive)
+                              (memory-usage-format xdead)
+                              (car x))
+                    (format "\t%s in %s\n"
+                            (memory-usage-format xlive)
+                            (car x))))
+          (setq live (+ live xlive))
+          (if xdead (setq dead (+ dead xdead)))))
+
+      (insert (format "\nTotal in lisp objects: %s (live %s, dead %s)\n\n"
+                      (memory-usage-format (+ dead live))
+                      (memory-usage-format live)
+                      (memory-usage-format dead))))
+
+    (insert
+     (format "Buffer ralloc memory usage:\n%d buffers\n%s total (%s in gaps)\n"
+             num
+             (memory-usage-format
+              (apply #'+ (mapcar #'memory-usage-buffer-total-bytes bufs)))
+             (memory-usage-format
+              (apply #'+ (mapcar #'memory-usage-buffer-gap-bytes bufs)))))
     (insert (format "%10s\t%s\t%s\n\n" "Size" "Gap" "Name"))
     (insert (mapconcat
             (lambda (b)
     (insert "\n"))
   (goto-char (point-min)))
 
+(defun memory-usage-find-large-variables ()
+  "Find variables whose printed representation takes over 100KB."
+  (interactive)
+  (let ((min-size (* 100 1024)))
+    (pop-to-buffer "*Memory Explorer*")
+    (delete-region (point-min) (point-max))
+    ;; First find large global variables.
+    (mapatoms
+     (lambda (sym)
+       (let ((size (or (and (boundp sym)
+                            (length (prin1-to-string (symbol-value sym))))
+                       0)))
+         (when (> size min-size)
+           (insert (format "%d\tGlobal\t%s\n"
+                           size
+                           (symbol-name sym)))))))
+    ;; Second find large buffer-local variables.
+    (mapc
+     (lambda (buffer)
+       (let ((holder ""))
+         (with-current-buffer buffer
+           (mapc
+            (lambda (var-cons)
+              (let ((size (or (and (consp var-cons)
+                                   (length (prin1-to-string (cdr var-cons))))
+                              0)))
+                (if (> size min-size)
+                    (setq holder (format "%d\t%s\t%s\n"
+                                         size (buffer-name buffer)
+                                         (symbol-name (car var-cons)))))))
+            (buffer-local-variables)))
+         (insert holder)))
+     (buffer-list))
+    (sort-numeric-fields 1 (point-min) (point-max))))
 
 (provide 'memory-usage)
-;; arch-tag: 04e012f0-3c59-4319-8d1a-e86204671ec5
 ;;; memory-usage.el ends here