;;; 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
;;; Commentary:
-;;
+;; See Info node `(elisp)Profiling'.
;;; Code:
(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)
(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)))
(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
(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*"
(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."