emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/emacs-gc-stats 7a454887a1 02/24: Initial implemention


From: ELPA Syncer
Subject: [elpa] externals/emacs-gc-stats 7a454887a1 02/24: Initial implemention
Date: Sat, 10 Jun 2023 12:58:44 -0400 (EDT)

branch: externals/emacs-gc-stats
commit 7a454887a112be689a003754376385b08013b486
Author: Ihor Radchenko <yantar92@posteo.net>
Commit: Ihor Radchenko <yantar92@posteo.net>

    Initial implemention
---
 emacs-gc-stats.el | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 2 deletions(-)

diff --git a/emacs-gc-stats.el b/emacs-gc-stats.el
index 143a740462..e80e0e37ef 100644
--- a/emacs-gc-stats.el
+++ b/emacs-gc-stats.el
@@ -3,7 +3,6 @@
 ;; Copyright (C) 2023  Ihor Radchenko
 
 ;; Author: Ihor Radchenko <yantar92@posteo.net>
-;; Keywords: 
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
@@ -19,12 +18,133 @@
 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 ;;; Commentary:
-
+;;
+;; This package collects Emacs garbage statistics over time and saves
+;; it in the format that can be shared with Emacs maintainers.
+;;
+;;; Usage:
+;;
+;; Add
+;; (require 'emacs-gc-stats)
+;; (emacs-gc-stats-mode +1)
+;; to your init file to enable the statistics acquiring.
+;;
+;; When you are ready to share the results, run
+;; M-x emacs-gc-stats-submit
 
 ;; 
 ;;; Code:
 
+(defgroup emacs-gc-stats nil
+  "Collect and share Emacs GC statistics."
+  :tag "GC stats"
+  :group 'development)
+
+(defcustom emacs-gc-stats-file (expand-file-name "emacs-gc-stats.eld" 
user-emacs-directory)
+  "File used to store the statistics across Emacs sessions."
+  :type 'file)
+
+(defvar emacs-gc-stats--setting-vars
+  '(gc-cons-threshold
+    gc-cons-percentage
+    memory-limit
+    emacs-version)
+  "List of variable/function symbols to collect.")
+
+(defvar emacs-gc-stats--command-vars
+  '(gc-cons-threshold
+    gc-cons-percentage
+    gcmh-mode
+    gc-elapsed
+    gcs-done
+    this-command
+    memory-limit
+    memory-info)
+  "List of variable/function symbols to collect for each GC or command.")
+
+(defvar emacs-gc-stats--summary-vars
+  '(gc-cons-threshold
+    gc-cons-percentage
+    gc-elapsed
+    gcs-done
+    memory-limit
+    emacs-uptime)
+  "List of variables to collect at session end.")
+
+(defun emacs-gc-stats--collect (&rest symbols)
+  "Collect SYMBOLS values.
+If symbol is a variable, collect (symbol . value).
+If symbol is a function name, collect (symbol . (funcall symbol)).
+If symbol is a list, collect (symbol . (eval symbol)).
+Otherwise, collect symbol."
+  (let (data)
+    (dolist (var symbols)
+      (pcase var
+        ((pred keywordp) (push var data))
+        ((and (pred symbolp) (pred boundp))
+         (push (cons var (symbol-value var)) data))
+        ((pred functionp)
+         (push (cons var (funcall var)) data))
+        ((pred listp)
+         (push (cons var (eval var)) data))
+        (_ (push var data))))
+    (nreverse data)))
+
+(defvar emacs-gc-stats--data nil
+  "Collected statistics.")
+
+(defun emacs-gc-stats--collect-init ()
+  "Collect initial stats."
+  (push
+   (apply #'emacs-gc-stats--collect
+          "Initial stats"
+          :time (current-time-string)
+          emacs-gc-stats--setting-vars)
+   emacs-gc-stats--data))
+
+(defun emacs-gc-stats--collect-gc ()
+  "Collect single GC stats."
+  (push
+   (apply #'emacs-gc-stats--collect
+          :time (current-time-string)
+          emacs-gc-stats--command-vars)
+   emacs-gc-stats--data))
+
+(defun emacs-gc-stats--collect-end ()
+  "Collect initial stats."
+  (push
+   (apply #'emacs-gc-stats--collect
+          "Session end stats"
+          :time (current-time-string)
+          emacs-gc-stats--summary-vars)
+   emacs-gc-stats--data))
+
+(defun emacs-gc-stats-save-session ()
+  "Save stats to disk."
+  (interactive)
+  (emacs-gc-stats--collect-end)
+  (let ((previous-sessions
+         (and (file-readable-p emacs-gc-stats-file)
+              (with-temp-buffer
+                (insert-file-contents emacs-gc-stats-file)
+                (ignore-errors (read (current-buffer)))))))
+    (with-temp-file emacs-gc-stats-file
+      ;; Override partially saved session.
+      (setf (alist-get (car emacs-gc-stats--data) previous-sessions)
+            (cdr emacs-gc-stats--data))
+      (prin1 previous-sessions (current-buffer)))))
 
+(define-minor-mode emacs-gc-stats-mode
+  "Toggle collecting Emacs GC statistics."
+  :global t
+  (if emacs-gc-stats-mode
+      (progn
+        (unless emacs-gc-stats--data
+          (emacs-gc-stats--collect-init))
+        (add-hook 'post-gc-hook #'emacs-gc-stats--collect-gc)
+        (add-hook 'kill-emacs-hook #'emacs-gc-stats-save-session))
+    (remove-hook 'post-gc-hook #'emacs-gc-stats--collect-gc)
+    (remove-hook 'kill-emacs-hook #'emacs-gc-stats-save-session)))
 
 (provide 'emacs-gc-stats)
 ;;; emacs-gc-stats.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]