]> git.eshelyaron.com Git - emacs.git/commitdiff
(load-path-filter-cache-directory-files): Filter only for `must-suffix`
authorStefan Monnier <monnier@iro.umontreal.ca>
Sat, 31 May 2025 17:29:05 +0000 (13:29 -0400)
committerEshel Yaron <me@eshelyaron.com>
Sat, 7 Jun 2025 19:59:13 +0000 (21:59 +0200)
Most loads set the `must-suffix` (e.g. `require and
`autoload-do-load`), but some don't (e.g. `load-library`).
This results in two separate entries in
`load-path-filter--cache` with two hash-tables.  The entry for
`must-suffix=nil` is larger and much less often used than the
other, so just skip filtering when `must-suffix=nil`.
Reduces the memory size of the cache from ~1MB to ~400kB in my
test case.

* lisp/startup.el (load-path-filter-cache-directory-files):
Don't use a filtering cache when `must-suffix` is nil.

(cherry picked from commit c3d9581f84107c2e137c71bb8fbf386bc20c944c)

lisp/startup.el

index ffa4cc522d75066a2a3fd29d957231e3eeebae76..873488312cef3e85671a2b2324ee58ccfcc42b04 100644 (file)
@@ -1102,11 +1102,12 @@ the `--debug-init' option to view a complete error backtrace."
 
 The value is an alist.  The car of each entry is a list of load suffixes,
 such as returned by `get-load-suffixes'.  The cdr of each entry is a
-cons whose car is an `regex-opt' optimized regex matching those suffixes
+cons whose car is a regex matching those suffixes
 at the end of a string, and whose cdr is a hash-table mapping directories
 to files in those directories which end with one of the suffixes.
-Since the list of load suffixes usually includes an empty string, the
-hash-table will also include subdirectories of those directories.
+These can also be nil, in which case no filtering will happen.
+The files named in the hash-table can be of any kind,
+including subdirectories.
 The hash-table uses `equal' as its key comparison function.")
 
 (defun load-path-filter-cache-directory-files (path file suffixes)
@@ -1124,19 +1125,28 @@ This function is called from `load' via `load-path-filter-function'."
   (if (file-name-directory file)
       ;; FILE has more than one component, don't bother filtering.
       path
-    (seq-filter
-     (let ((rx-and-ht
-            (with-memoization (alist-get suffixes load-path-filter--cache nil nil #'equal)
-              (cons
-               (concat (regexp-opt suffixes) "\\'")
-               (make-hash-table :test #'equal)))))
-       (lambda (dir)
-         (when (file-directory-p dir)
-           (try-completion
-            file
-            (with-memoization (gethash dir (cdr rx-and-ht))
-              (directory-files dir nil (car rx-and-ht) t))))))
-     path)))
+    (pcase-let
+        ((`(,rx . ,ht)
+          (with-memoization (alist-get suffixes load-path-filter--cache
+                                       nil nil #'equal)
+            (if (member "" suffixes)
+                '(nil ;; Optimize the filtering.
+                  ;; Don't bother filtering if "" is among the suffixes.
+                  ;; It's a much less common use-case and it would use
+                  ;; more memory to keep the corresponding info.
+                  . nil)
+              (cons (concat (regexp-opt suffixes) "\\'")
+                    (make-hash-table :test #'equal))))))
+      (if (null ht)
+          path
+        (seq-filter
+         (lambda (dir)
+           (when (file-directory-p dir)
+             (try-completion
+              file
+              (with-memoization (gethash dir ht)
+                (directory-files dir nil rx t)))))
+         path)))))
 
 (defun command-line ()
   "A subroutine of `normal-top-level'.