[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Emacs 23.0 is much slower starting than Emacs 22.3

From: David De La Harpe Golden
Subject: Re: Emacs 23.0 is much slower starting than Emacs 22.3
Date: Sat, 25 Oct 2008 00:44:56 +0100
User-agent: Mozilla-Thunderbird (X11/20081018)

Stefan Monnier wrote:

Setting vc-handled-backends to nil should indeed stop VC from doing
those directory walks.  So now I don't understand why the walks done by
VC are so much cheaper than the ones done by locate-dominating-file.
Could it be that all the files you opened were under CVS control (so
the VC search stops before having to walk up the directories)?

Eventually found vc-find-root. So - it versus locate-dominating-file ?

While they're doing a fairly similar job, they do look to me like they're implemented importantly differently -locate-dominating-file takes a regex and passes it to directory-files for each directory. AFAICS directory-files scans the whole directory each time through for the match. OTOH, vc-find-root just tests if /path/to/directory/witness exists. The former is rather slower and (I think) consier. I'm not sure that there's any real performance problem with directory-files itself for what it actually does, though maybe it could be made faster. Maybe not worthwhile though - easier to rewrite locate-dominating-file to not use it as below...

Profiling says locate-dominating-file is spending most all its time in directory-files trying that doomed match again and again...

find-file-noselect         1108        48.279532999  0.0435735857
find-file-noselect-1       1108        29.139766999  0.0262994287
after-find-file            1108        26.323623999  0.0237577833
normal-mode                1108        21.492128000  0.0193972274
hack-local-variables       1108        19.570003     0.0176624575
hack-project-variables     1108        19.266695999  0.0173887148
project-find-settings-file 1108        19.254854999  0.0173780279
locate-dominating-file     1108        19.237415000  0.0173622879
directory-files            4152        18.688168999  0.0045010040

So is locate-dominating-file's regex-matching really necessary in project-find-settings-file? The only call to locate-dominating-file I can see is it just searching for a (hardcoded name) ".dir.settings.el" in project-find-settings-file, so vc-find-root's rather simpler witness technique would work just fine?

+++ And indeed, attached patch makes emacs23 1108-file-startup rather more competitive with emacs22 on my system. Though I didn't do much testing to see if project settings functionality was 100% a-okay -
though it seemed to pick up a /usr/local/src/emacs-22.3/.dir-settings.el
I made okay...

emacs   patch   withsettings    realtime
22      n/a     n/a             22.853
23      no      no              38.518
23      no      yes             38.729
23      yes     no              23.295
23      yes     yes             23.340

Index: lisp/files.el
RCS file: /sources/emacs/emacs/lisp/files.el,v
retrieving revision 1.1005
diff -U 8 -r1.1005 files.el
--- lisp/files.el       18 Oct 2008 18:40:25 -0000      1.1005
+++ lisp/files.el       24 Oct 2008 23:37:19 -0000
@@ -711,18 +711,59 @@
 (defun locate-file-completion (string path-and-suffixes action)
   "Do completion for file names passed to `locate-file'.
   (locate-file-completion-table (car path-and-suffixes)
                                 (cdr path-and-suffixes)
                                 string nil action))
 (make-obsolete 'locate-file-completion 'locate-file-completion-table "23.1")
-(defun locate-dominating-file (file regexp)
-  "Look up the directory hierarchy from FILE for a file matching REGEXP."
+(defun locate-dominating-file (file name)
+   "Look up the directory hierarchy from FILE for a file named NAME.
+If found, return the file named NAME's full name and path, otherwise
+return nil. See locate-dominating-file-by-regexp if you have more
+complex requirements than a simple whole-string match on the name,
+though beware it is slower."
+   ;; copied from vc-find-root, then changed to return file
+   ;; rather than containing dir.
+   ;; Represent /home/luser/foo as ~/foo so that we don't try to look for
+   ;; witnesses in /home or in /.
+   (setq file (abbreviate-file-name file))
+   (let ((root nil)
+        (prev-file file)
+        ;; `user' is not initialized outside the loop because
+        ;; `file' may not exist, so we may have to walk up part of the
+        ;; hierarchy before we find the "initial UID".
+        (user nil)
+        try)
+     (while (not (or root
+                    (null file)
+                    ;; As a heuristic, we stop looking up the hierarchy of
+                    ;; directories as soon as we find a directory belonging
+                    ;; to another user.  This should save us from looking in
+                    ;; things like /net and /afs.  This assumes that all the
+                    ;; files inside a project belong to the same user.
+                    (let ((prev-user user))
+                      (setq user (nth 2 (file-attributes file)))
+                      (and prev-user (not (equal user prev-user))))
+                    (string-match
+                     ;; from vc-ignore-dir-regexp !
+                     file)))
+       (setq try (file-exists-p (expand-file-name name file)))
+       (cond (try (setq root file))
+            ((equal file (setq prev-file file
+                               file (file-name-directory
+                                     (directory-file-name file))))
+             (setq file nil))))
+     (when root (expand-file-name name root))))
+(defun locate-dominating-file-by-regexp (file regexp)
+  "Look up the directory hierarchy from FILE for a file matching REGEXP.
+This function is slower than `locate-dominating-file', only use if necessary."
   (catch 'found
     ;; `user' is not initialized yet because `file' may not exist, so we may
     ;; have to walk up part of the hierarchy before we find the "initial UID".
     (let ((user nil)
           ;; Abbreviate, so as to stop when we cross ~/.
           (dir (abbreviate-file-name (file-name-as-directory file)))
       (while (and dir
@@ -3154,17 +3195,17 @@
 (defun project-find-settings-file (file)
   "Find the settings file for FILE.
 This searches upward in the directory tree.
 If a settings file is found, the file name is returned.
 If the file is in a registered project, a cons from
 `project-directory-alist' is returned.
 Otherwise this returns nil."
   (setq file (expand-file-name file))
-  (let* ((settings (locate-dominating-file file "\\`\\.dir-settings\\.el\\'"))
+  (let* ((settings (locate-dominating-file file ".dir-settings.el"))
          (pda nil))
     ;; `locate-dominating-file' may have abbreviated the name.
     (if settings (setq settings (expand-file-name settings)))
     (dolist (x project-directory-alist)
       (when (and (eq t (compare-strings file nil (length (car x))
                                         (car x) nil nil))
                  (> (length (car x)) (length (car pda))))
         (setq pda x)))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]