]> code.delx.au - gnu-emacs/blobdiff - lisp/profiler.el
Merge from trunk after a lot of time.
[gnu-emacs] / lisp / profiler.el
index e9261eb1af7df941510f132d6d754de8fe7099c9..609a0308cf09026f10068423db11c6b832891f79 100644 (file)
@@ -1,26 +1,28 @@
 ;;; profiler.el --- UI and helper functions for Emacs's native profiler -*- lexical-binding: t -*-
 
-;; Copyright (C) 2012 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
 
 ;; Author: Tomohiro Matsuyama <tomo@cx4a.org>
 ;; Keywords: lisp
 
-;; This program is free software; you can redistribute it and/or modify
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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 3 of the License, or
 ;; (at your option) any later version.
 
-;; This program is distributed in the hope that it will be useful,
+;; GNU Emacs 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
-;;
+;; See Info node `(elisp)Profiling'.
 
 ;;; Code:
 
@@ -58,7 +60,7 @@
 (defun profiler-format-number (number)
   "Format NUMBER in human readable string."
   (if (and (integerp number) (> number 0))
-      (cl-loop with i = (% (1+ (floor (log10 number))) 3)
+      (cl-loop with i = (% (1+ (floor (log number 10))) 3)
               for c in (append (number-to-string number) nil)
               if (= i 0)
               collect ?, into s
@@ -200,11 +202,18 @@ function name of a function itself."
     (goto-char (point-min))
     (read (current-buffer))))
 
+(defun profiler-running-p (&optional mode)
+  "Return non-nil if the profiler is running.
+Optional argument MODE means only check for the specified mode (cpu or mem)."
+  (cond ((eq mode 'cpu) (and (fboundp 'profiler-cpu-running-p)
+                             (profiler-cpu-running-p)))
+        ((eq mode 'mem) (profiler-memory-running-p))
+        (t (or (profiler-running-p 'cpu)
+               (profiler-running-p 'mem)))))
+
 (defun profiler-cpu-profile ()
   "Return CPU profile."
-  (when (and (fboundp 'profiler-cpu-running-p)
-             (fboundp 'profiler-cpu-log)
-             (profiler-cpu-running-p))
+  (when (profiler-running-p 'cpu)
     (profiler-make-profile
      :type 'cpu
      :timestamp (current-time)
@@ -353,7 +362,9 @@ this variable directly.")
                  (propertize (symbol-name entry)
                              'face 'link
                              'mouse-face 'highlight
-                             'help-echo "mouse-2 or RET jumps to definition"))
+                             'help-echo "\
+mouse-2: jump to definition\n\
+RET: expand or collapse"))
                 (t
                  (profiler-format-entry entry)))))
     (propertize string 'profiler-entry entry)))
@@ -402,7 +413,6 @@ this variable directly.")
 
 (defvar profiler-report-mode-map
   (let ((map (make-sparse-keymap)))
-    ;; FIXME: Add menu.
     (define-key map "n"            'profiler-report-next-entry)
     (define-key map "p"            'profiler-report-previous-entry)
     ;; I find it annoying more than helpful to not be able to navigate
@@ -422,8 +432,50 @@ this variable directly.")
     (define-key map "D"            'profiler-report-descending-sort)
     (define-key map "="            'profiler-report-compare-profile)
     (define-key map (kbd "C-x C-w") 'profiler-report-write-profile)
-    (define-key map "q"     'quit-window)
-    map))
+    (easy-menu-define  profiler-report-menu map "Menu for Profiler Report mode."
+      '("Profiler"
+        ["Next Entry" profiler-report-next-entry :active t
+         :help "Move to next entry"]
+        ["Previous Entry" profiler-report-previous-entry :active t
+         :help "Move to previous entry"]
+        "--"
+        ["Toggle Entry" profiler-report-toggle-entry
+         :active (profiler-report-calltree-at-point)
+         :help "Expand or collapse the current entry"]
+        ["Find Entry" profiler-report-find-entry
+         ;; FIXME should deactivate if not on a known function.
+         :active (profiler-report-calltree-at-point)
+         :help "Find the definition of the current entry"]
+        ["Describe Entry" profiler-report-describe-entry
+         :active (profiler-report-calltree-at-point)
+         :help "Show the documentation of the current entry"]
+        "--"
+        ["Show Calltree" profiler-report-render-calltree
+         :active profiler-report-reversed
+         :help "Show calltree view"]
+        ["Show Reversed Calltree" profiler-report-render-reversed-calltree
+         :active (not profiler-report-reversed)
+         :help "Show reversed calltree view"]
+        ["Sort Ascending" profiler-report-ascending-sort
+         :active (not (eq profiler-report-order 'ascending))
+         :help "Sort calltree view in ascending order"]
+        ["Sort Descending" profiler-report-descending-sort
+         :active (not (eq profiler-report-order 'descending))
+         :help "Sort calltree view in descending order"]
+        "--"
+        ["Compare Profile..." profiler-report-compare-profile :active t
+         :help "Compare current profile with another"]
+        ["Write Profile..." profiler-report-write-profile :active t
+         :help "Write current profile to a file"]
+        "--"
+        ["Start Profiler" profiler-start :active (not (profiler-running-p))
+         :help "Start profiling"]
+        ["Stop Profiler" profiler-stop :active (profiler-running-p)
+         :help "Stop profiling"]
+        ["New Report" profiler-report :active (profiler-running-p)
+         :help "Make a new report"]))
+      map)
+  "Keymap for `profiler-report-mode'.")
 
 (defun profiler-report-make-buffer-name (profile)
   (format "*%s-Profiler-Report %s*"
@@ -527,11 +579,15 @@ otherwise collapse."
 (defun profiler-report-find-entry (&optional event)
   "Find entry at point."
   (interactive (list last-nonmenu-event))
-  (if event (posn-set-point (event-end event)))
-  (let ((tree (profiler-report-calltree-at-point)))
-    (when tree
-      (let ((entry (profiler-calltree-entry tree)))
-       (find-function entry)))))
+  (with-current-buffer
+      (if event (window-buffer (posn-window (event-start event)))
+        (current-buffer))
+    (and event (setq event (event-end event))
+         (posn-set-point event))
+    (let ((tree (profiler-report-calltree-at-point)))
+      (when tree
+        (let ((entry (profiler-calltree-entry tree)))
+          (find-function entry))))))
 
 (defun profiler-report-describe-entry ()
   "Describe entry at point."