Fetch the repository succeeded.
;;; profile-dotemacs.el --- Profile your Emacs init file;; Copyright (C) 2010, 2012 David Engster;; Author: David Engster <firstname.lastname@example.org>;; This file is NOT part of GNU Emacs.;; 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 the Free Software Foundation; either version 2;; of the License, or (at your option) any later version.;;;; This program 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/>.;;; Commentary:;; This is to easily profile your Emacs init file (or any other;; script-like Emacs Lisp file, for that matter).;; It will go over all sexp's (balanced expressions) in the file and;; run them through `benchmark-run'. It will then show the file with;; overlays applied in a way that let you easily find out which sexp's;; take the most time. Since time is relative, it's not the absolute;; value that counts but the percentage of the total running time.;;;; * All other sexp's with a percentage greater than;; `profile-dotemacs-low-percentage' will be preceded by a;; highlighted line, showing the results from `benchmark-run'.;; Also, the more 'reddish' the background of the sexp, the more;; time it needs.;; * All other sexp's will be grayed out to indicate that their;; running time is miniscule. You can still see the benchmark;; results in the minibuffer by hovering over the sexp with the;; mouse.;; You can only benchmark full sexp's, so if you wrapped large parts;; of your init file in some conditional clause, you'll have to remove;; that for getting finer granularity.;;; Usage:;; Start emacs as follows:;;;; emacs -Q -l <PATH>/profile-dotemacs.el -f profile-dotemacs;;;; with <PATH> being the path to where this file resides.;;; Caveats (thanks to Raffaele Ricciardi for reporting those):;; - The usual `--debug-init' for debugging your init file won't work;; with profile-dotemacs, so you'll have to call;; `toggle-debug-on-error', either on the commandline or at the;; beginning of your init file.;; - `load-file-name' is nil when the init file is being loaded;; by the profiler. This might matter if you perform the;; bulk of initializations in a different file.;; - Starting external shells like IELM or eshell in your init file;; might mess with overlay creation, so this must not be done.;;; Download:;; You can always get the latest version from;; http://randomsample.de/profile-dotemacs.el;;; Code:(require 'thingatpt)(require 'benchmark);; User variables(defvar profile-dotemacs-file "~/.emacs.d/init.el""File to be profiled.")(defvar profile-dotemacs-low-percentage 3"Percentage which should be considered low.All sexp's with a running time below this percentage will begrayed out.")(defface profile-dotemacs-time-face'((((background dark)) (:background "OrangeRed1"))(t (:background "red3")))"Background color to indicate percentage of total time.")(defface profile-dotemacs-low-percentage-face'((((background dark)) (:foreground "gray25"))(t (:foreground "gray75")))"Face for sexps below `profile-dotemacs-low-percentage'.")(defface profile-dotemacs-highlight-face'((((background dark)) (:background "blue"))(t (:background "yellow")))"Highlight face for benchmark results.");; Main function(defun profile-dotemacs ()"Load `profile-dotemacs-file' and benchmark its sexps."(interactive)(with-current-buffer (find-file-noselect profile-dotemacs-file t)(setq buffer-read-only t) ;; just to be sure(goto-char (point-min))(let (start end results)(while(< (point)(setq end (progn(forward-sexp 1)(point))))(forward-sexp -1)(setq start (point))(add-to-list'results`(,start ,end,(benchmark-run(eval (sexp-at-point)))))(goto-char end))(profile-dotemacs-show-results results)(switch-to-buffer (current-buffer)))));; Helper functions(defun profile-dotemacs-show-results (results)"Show timings from RESULTS in current buffer."(let ((totaltime (profile-dotemacs-totaltime results))current percentage ov)(while results(let* ((current (pop results))(ov (make-overlay (car current) (cadr current)))(current (car (last current)))(percentage (/ (+ (car current) (nth 2 current))totaltime))col benchstr lowface)(setq col(profile-dotemacs-percentage-colorpercentage(face-background 'default)(face-background 'profile-dotemacs-time-face)))(setq percentage (round (* 100 percentage)))(setq benchstr (profile-dotemacs-make-benchstr current))(overlay-put ov 'help-echo benchstr)(if (and (numberp profile-dotemacs-low-percentage)(< percentage profile-dotemacs-low-percentage))(overlay-put ov 'face 'profile-dotemacs-low-percentage-face)(overlay-put ov 'before-string(propertize benchstr'face 'profile-dotemacs-highlight-face))(overlay-put ov 'face`(:background ,col)))))(setq ov (make-overlay (1- (point-max)) (point-max)))(overlay-put ov 'after-string(propertize(format "\n-----------------\nTotal time: %.2fs\n"totaltime)'face 'profile-dotemacs-highlight-face))))(defun profile-dotemacs-totaltime (results)"Calculate total time of RESULTS."(let ((totaltime 0))(mapc (lambda (x)(let ((cur (car (last x))))(setq totaltime (+ totaltime (car cur) (nth 2 cur)))))results)totaltime))(defun profile-dotemacs-percentage-color (percent col-begin col-end)"Calculate color according to PERCENT between COL-BEGIN and COL-END."(let* ((col1 (color-values col-begin))(col2 (color-values col-end))(col(mapcar (lambda (c)(round(+ (* (- 1 percent) (nth c col1))(* percent (nth c col2)))))'(0 1 2))))(format "RGB:%04x/%04x/%04x"(car col)(nth 1 col)(nth 2 col))))(defun profile-dotemacs-make-benchstr (timings)"Create descriptive benchmark string from TIMINGS."(format(concat"<Percentage: %d ; ""Time: %.2f ; ""Number of GC: %d ; ""Time for GC: %.2f>\n")percentage(car timings) (nth 1 timings) (nth 2 timings)));; profile-dotemacs.el ends here