diff lisp/cus-dep.el @ 1298:1b4bc72f433e

[xemacs-hg @ 2003-02-14 12:05:06 by ben] speedups to build process autoload.el: Factor out common code in generate-{c-,}file-autoloads-1 into new function generate-autoload-ish-1. \(I was originally going to use this for custom as well but ended up thinking better of it.) cus-dep.el: Cache the old computed values in custom-load.el and reuse them as necessary, to speed up running cus-dep (which would take 25-30 seconds to do all files in lisp/*, lisp/*/* on my Pentium III 700). Use `message' not `princ' to get correct newline behavior. Output messages showing each file we do actually process. update-elc-2.el: Rewrite algorithm to be much faster -- cache calls to directory-files and don't make needless calls to file-exists-p, file-directory-p because they're way way slow. Autoload early and only when update-elc has told us to. update-elc.el: If no files need byte compilation, signal to update-elc-2 to do any necessary autoload updating (using the file REBUILD_AUTOLOADS) rather than doing it ourselves, which would be way slow. Ignore updates to custom-load.el and auto-autoloads.el when checking to see whether autoloads need updating. Optimize out many unnecessary calls to file-exists-p to speed it up somewhat. (#### The remaining time is 50% or more in locate-file; this is presumably because, even though it has a cache, it's still statting each file to determine it's actually there. By calling directory-files ourselves, building a tree, and then looking in that tree, we could drastically shorten the time needed to do the locate operation.)
author ben
date Fri, 14 Feb 2003 12:05:07 +0000
parents 78c3f60ba757
children b4a8cd0dd8df
line wrap: on
line diff
--- a/lisp/cus-dep.el	Fri Feb 14 11:50:36 2003 +0000
+++ b/lisp/cus-dep.el	Fri Feb 14 12:05:07 2003 +0000
@@ -1,6 +1,7 @@
 ;;; cus-dep.el --- Find customization dependencies.
 ;;
 ;; Copyright (C) 1997 Free Software Foundation, Inc.
+;; Copyright (C) 2003 Ben Wing.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>, then
 ;;         Richard Stallman <rms@gnu.ai.mit.edu>, then
@@ -76,6 +77,11 @@
 ;; files.  This is not necessary under FSF (they simply use `put'),
 ;; since they have only one file with custom dependencies.  With the
 ;; advent of packages, we cannot afford the same luxury.
+;;
+;; Feb 2003: Added code to speed up building by caching the values we've
+;; constructed, and using them instead of scanning a file when custom-load
+;; is up-to-date w.r.t. the file.  Also use `message' not `princ' to print
+;; out messages so nl's are correctly inserted when necessary. --ben
 
 
 ;;; Code:
@@ -90,6 +96,7 @@
 ;; Don't change this, unless you plan to change the code in
 ;; cus-start.el, too.
 (defconst cusload-base-file "custom-load.el")
+(defconst cusload-hash-table-marker ";old-cus-dep-hash: ")
 
 ;; Be very careful when changing this function.  It looks easy to
 ;; understand, but is in fact very easy to break.  Be sure to read and
@@ -99,9 +106,11 @@
   (setq subdirs (mapcar #'expand-file-name subdirs))
   (with-temp-buffer
     (let ((enable-local-eval nil)
-	  (hash (make-hash-table :test 'eq)))
+	  (hash (make-hash-table :test 'eq))
+	  (hash-cache (make-hash-table :test 'equal))
+	  old-hash)
       (dolist (dir subdirs)
-	(princ (format "Processing %s\n" dir))
+	(message "Processing %s\n" dir)
 	(let ((cusload-file (expand-file-name cusload-base-file dir))
 	      (files (directory-files dir t "\\`[^=].*\\.el\\'")))
 	  ;; A trivial optimization: if no file in the directory is
@@ -110,46 +119,77 @@
 		   (dolist (file files t)
 		     (when (file-newer-than-file-p file cusload-file)
 		       (return nil))))
-	      (princ "(No changes need to be written)\n")
+	      (message "(No changes need to be written)")
+	    (when (file-exists-p cusload-file)
+	      (let ((buf (find-file-noselect cusload-file)))
+		(with-current-buffer buf
+		  (goto-char (point-min))
+		  (when (search-forward cusload-hash-table-marker nil t)
+		    (setq old-hash (read buf))))
+		(kill-buffer buf)))
 	    ;; Process directory
 	    (dolist (file files)
-	      (when (file-exists-p file)
-		(erase-buffer)
-		(insert-file-contents file)
-		(goto-char (point-min))
-		(let ((name (file-name-sans-extension
-			     (file-name-nondirectory file))))
-		  ;; Search for defcustom/defface/defgroup
-		  ;; expressions, and evaluate them.
-		  (while (re-search-forward
-			  "^(defcustom\\|^(defface\\|^(defgroup"
-			  nil t)
-		    (beginning-of-line)
-		    (let ((expr (read (current-buffer))))
-		      ;; We need to ignore errors here, so that
-		      ;; defcustoms with :set don't bug out.  Of
-		      ;; course, their values will not be assigned in
-		      ;; case of errors, but their `custom-group'
-		      ;; properties will by that time be in place, and
-		      ;; that's all we care about.
-		      (ignore-errors
-			(eval expr))
-		      ;; Hash the file of the affected symbol.
-		      (setf (gethash (nth 1 expr) hash) name))))))
+	      (let ((old-cache (if (hash-table-p old-hash)
+				   (gethash file old-hash t)
+				 t)))
+		(if (and (not (file-newer-than-file-p file cusload-file))
+			 (not (eq old-cache t)))
+		    (progn
+		      (dolist (c old-cache)
+			(puthash (car c) (cdr c) hash))
+		      (puthash file old-cache hash-cache))
+		  (erase-buffer)
+		  (insert-file-contents file)
+		  (goto-char (point-min))
+		  (let ((name (file-name-sans-extension
+			       (file-name-nondirectory file)))
+			cache
+			(first t))
+		    ;; Search for defcustom/defface/defgroup
+		    ;; expressions, and evaluate them.
+		    (while (re-search-forward
+			    "^(defcustom\\|^(defface\\|^(defgroup"
+			    nil t)
+		      (when first
+			(message "Computing custom-loads for %s..." name)
+			(setq first nil))
+		      (beginning-of-line)
+		      (let ((expr (read (current-buffer))))
+			;; We need to ignore errors here, so that
+			;; defcustoms with :set don't bug out.  Of
+			;; course, their values will not be assigned in
+			;; case of errors, but their `custom-group'
+			;; properties will by that time be in place, and
+			;; that's all we care about.
+			(ignore-errors
+			  (eval expr))
+			;; Hash the file of the affected symbol.
+			(setf (gethash (nth 1 expr) hash) name)
+			;; Remember the values computed.
+			(push (cons (nth 1 expr) name) cache)))
+		    (or cache
+			(message "No custom-loads for %s" name))
+		    (puthash file cache hash-cache)))
+		))
 	    (cond
 	     ((zerop (hash-table-count hash))
-	      (princ "(No customization dependencies")
-	      (when (file-exists-p cusload-file)
-		(princ (format ", deleting %s" cusload-file))
-		(delete-file cusload-file))
-	      (princ ")\n"))
+	      (if (not (file-exists-p cusload-file))
+		  (message "(No customization dependencies)")
+		(message "(No customization dependencies, deleting %s)"
+			 cusload-file)
+		(delete-file cusload-file)))
 	     (t
-	      (princ (format "Generating %s...\n" cusload-base-file))
+	      (message "Generating %s...\n" cusload-base-file)
 	      (with-temp-file cusload-file
 		(insert ";;; " cusload-base-file
 			" --- automatically extracted custom dependencies\n"
-			"\n;;; Code:\n\n"
-			"(autoload 'custom-add-loads \"cus-load\")\n\n")
+			"\n;;; Code:\n\n")
+		(insert cusload-hash-table-marker)
+		(let ((print-readably t)
+		      (standard-output (current-buffer)))
+		  (princ hash-cache)
+		  (terpri))
+		(insert "(autoload 'custom-add-loads \"cus-load\")\n\n")
 		(mapatoms
 		 (lambda (sym)
 		   (let ((members (get sym 'custom-group))