unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
blob b86b56b81ec6938ebd7521999b1d0968865537b5 4134 bytes (raw)
name: lisp/emacs-lisp/benchmark.el 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
 
;;; benchmark.el --- support for benchmarking code  -*- lexical-binding: t -*-

;; Copyright (C) 2003-2018 Free Software Foundation, Inc.

;; Author: Dave Love  <fx@gnu.org>
;; Keywords: lisp, extensions

;; 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.

;; 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 GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; Utilities for timing the execution of forms, including the time
;; taken for GC.  Note that prior to timing code you may want to
;; ensure things like:  there has just been a GC, the relevant code is
;; already loaded (so that there's no overhead from autoloading etc.),
;; and the code is compiled if appropriate (but see
;; `benchmark-run-compiled').

;;; Code:

(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")))
    `(let (,t1)
       (setq ,t1 (current-time))
       ,@forms
       (float-time (time-subtract nil ,t1)))))

;;;###autoload
(defmacro benchmark-run (&optional repetitions &rest forms)
  "Time execution of FORMS.
If REPETITIONS is supplied as a number, run forms that many times,
accounting for the overhead of the resulting loop.  Otherwise run
FORMS once.
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)
    (setq forms (cons repetitions forms)
	  repetitions 1))
  (let ((i (make-symbol "i"))
	(gcs (make-symbol "gcs"))
	(gc (make-symbol "gc")))
    `(let ((,gc gc-elapsed)
	   (,gcs gcs-done))
       (list ,(if (> repetitions 1)
		  ;; Take account of the loop overhead.
		  `(- (benchmark-elapse (dotimes (,i ,repetitions)
					  ,@forms))
		      (benchmark-elapse (dotimes (,i ,repetitions))))
		`(benchmark-elapse ,@forms))
	     (- gcs-done ,gcs)
	     (- gc-elapsed ,gc)))))

;;;###autoload
(defmacro benchmark-run-compiled (&optional repetitions &rest forms)
  "Time execution of compiled version of FORMS.
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)
    (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 ()))))
    `(let ((,gc gc-elapsed)
	   (,gcs gcs-done))
       (list ,(if (> repetitions 1)
		  ;; Take account of the loop overhead.
		  `(- (benchmark-elapse (dotimes (,i ,repetitions)
					  (funcall ,code)))
		      (benchmark-elapse (dotimes (,i ,repetitions)
					  (funcall ,lambda-code))))
		`(benchmark-elapse (funcall ,code)))
	     (- gcs-done ,gcs) (- gc-elapsed ,gc)))))

;;;###autoload
(defun benchmark (repetitions form)
  "Print the time taken for REPETITIONS executions of FORM.
Interactively, REPETITIONS is taken from the prefix arg, and
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))))
    (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)))))

(provide 'benchmark)

;;; benchmark.el ends here

debug log:

solving b86b56b81e ...
found b86b56b81e in https://git.savannah.gnu.org/cgit/emacs.git

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).