Skip to content
Snippets Groups Projects
Select Git revision
  • 42ecd1423bb35fa810c89e894c5dc26c6d5b5510
  • master default protected
  • enxhi_issue460_remove_TOAR-I_access
  • michael_issue459_preprocess_german_stations
  • sh_pollutants
  • develop protected
  • release_v2.4.0
  • michael_issue450_feat_load-ifs-data
  • lukas_issue457_feat_set-config-paths-as-parameter
  • lukas_issue454_feat_use-toar-statistics-api-v2
  • lukas_issue453_refac_advanced-retry-strategy
  • lukas_issue452_bug_update-proj-version
  • lukas_issue449_refac_load-era5-data-from-toar-db
  • lukas_issue451_feat_robust-apriori-estimate-for-short-timeseries
  • lukas_issue448_feat_load-model-from-path
  • lukas_issue447_feat_store-and-load-local-clim-apriori-data
  • lukas_issue445_feat_data-insight-plot-monthly-distribution
  • lukas_issue442_feat_bias-free-evaluation
  • lukas_issue444_feat_choose-interp-method-cams
  • 414-include-crps-analysis-and-other-ens-verif-methods-or-plots
  • lukas_issue384_feat_aqw-data-handler
  • v2.4.0 protected
  • v2.3.0 protected
  • v2.2.0 protected
  • v2.1.0 protected
  • Kleinert_etal_2022_initial_submission
  • v2.0.0 protected
  • v1.5.0 protected
  • v1.4.0 protected
  • v1.3.0 protected
  • v1.2.1 protected
  • v1.2.0 protected
  • v1.1.0 protected
  • IntelliO3-ts-v1.0_R1-submit
  • v1.0.0 protected
  • v0.12.2 protected
  • v0.12.1 protected
  • v0.12.0 protected
  • v0.11.0 protected
  • v0.10.0 protected
  • IntelliO3-ts-v1.0_initial-submit
41 results

helpers.py

Blame
  • profile-dotemacs.el 6.48 KiB
    ;;; profile-dotemacs.el --- Profile your Emacs init file
    
    ;; Copyright (C) 2010, 2012  David Engster
    
    ;; Author: David Engster <dengste@eml.cc>
    
    ;; 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 be
    grayed 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-color
    	       percentage
    	       (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