summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/benchmark.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/benchmark.el')
-rw-r--r--lisp/emacs-lisp/benchmark.el46
1 files changed, 34 insertions, 12 deletions
diff --git a/lisp/emacs-lisp/benchmark.el b/lisp/emacs-lisp/benchmark.el
index 9c2def7af6d..278fb807fd5 100644
--- a/lisp/emacs-lisp/benchmark.el
+++ b/lisp/emacs-lisp/benchmark.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2003-2019 Free Software Foundation, Inc.
-;; Author: Dave Love <fx@gnu.org>
+;; Author: Dave Love <fx@gnu.org>
;; Keywords: lisp, extensions
;; This file is part of GNU Emacs.
@@ -34,13 +34,11 @@
(defmacro benchmark-elapse (&rest forms)
"Return the time in seconds elapsed for execution of FORMS."
(declare (indent 0) (debug t))
- (let ((t1 (make-symbol "t1"))
- (t2 (make-symbol "t2")))
- `(let (,t1 ,t2)
+ (let ((t1 (make-symbol "t1")))
+ `(let (,t1)
(setq ,t1 (current-time))
,@forms
- (setq ,t2 (current-time))
- (float-time (time-subtract ,t2 ,t1)))))
+ (float-time (time-since ,t1)))))
;;;###autoload
(defmacro benchmark-run (&optional repetitions &rest forms)
@@ -52,7 +50,7 @@ Return a list of the total elapsed time for execution, the number of
garbage collections that ran, and the time taken by garbage collection.
See also `benchmark-run-compiled'."
(declare (indent 1) (debug t))
- (unless (natnump repetitions)
+ (unless (or (natnump repetitions) (and repetitions (symbolp repetitions)))
(setq forms (cons repetitions forms)
repetitions 1))
(let ((i (make-symbol "i"))
@@ -60,7 +58,7 @@ See also `benchmark-run-compiled'."
(gc (make-symbol "gc")))
`(let ((,gc gc-elapsed)
(,gcs gcs-done))
- (list ,(if (> repetitions 1)
+ (list ,(if (or (symbolp repetitions) (> repetitions 1))
;; Take account of the loop overhead.
`(- (benchmark-elapse (dotimes (,i ,repetitions)
,@forms))
@@ -76,17 +74,17 @@ This is like `benchmark-run', but what is timed is a funcall of the
byte code obtained by wrapping FORMS in a `lambda' and compiling the
result. The overhead of the `lambda's is accounted for."
(declare (indent 1) (debug t))
- (unless (natnump repetitions)
+ (unless (or (natnump repetitions) (and repetitions (symbolp repetitions)))
(setq forms (cons repetitions forms)
repetitions 1))
(let ((i (make-symbol "i"))
(gcs (make-symbol "gcs"))
(gc (make-symbol "gc"))
(code (byte-compile `(lambda () ,@forms)))
- (lambda-code (byte-compile `(lambda ()))))
+ (lambda-code (byte-compile '(lambda ()))))
`(let ((,gc gc-elapsed)
(,gcs gcs-done))
- (list ,(if (> repetitions 1)
+ (list ,(if (or (symbolp repetitions) (> repetitions 1))
;; Take account of the loop overhead.
`(- (benchmark-elapse (dotimes (,i ,repetitions)
(funcall ,code)))
@@ -103,12 +101,36 @@ the command prompts for the form to benchmark.
For non-interactive use see also `benchmark-run' and
`benchmark-run-compiled'."
(interactive "p\nxForm: ")
- (let ((result (eval `(benchmark-run ,repetitions ,form))))
+ (let ((result (eval `(benchmark-run ,repetitions ,form) t)))
(if (zerop (nth 1 result))
(message "Elapsed time: %fs" (car result))
(message "Elapsed time: %fs (%fs in %d GCs)" (car result)
(nth 2 result) (nth 1 result)))))
+;;;###autoload
+(defmacro benchmark-progn (&rest body)
+ "Evaluate BODY and message the time taken.
+The return value is the value of the final form in BODY."
+ (declare (debug body) (indent 0))
+ (let ((value (make-symbol "value"))
+ (start (make-symbol "start"))
+ (gcs (make-symbol "gcs"))
+ (gc (make-symbol "gc")))
+ `(let ((,gc gc-elapsed)
+ (,gcs gcs-done)
+ (,start (current-time))
+ (,value (progn
+ ,@body)))
+ (message "Elapsed time: %fs%s"
+ (float-time (time-since ,start))
+ (if (> (- gcs-done ,gcs) 0)
+ (format " (%fs in %d GCs)"
+ (- gc-elapsed ,gc)
+ (- gcs-done ,gcs))
+ ""))
+ ;; Return the value of the body.
+ ,value)))
+
(provide 'benchmark)
;;; benchmark.el ends here