perf: cache module flags in symbol plists

For small amounts of data, symbol plists are the most efficient (space
and time wise) as data access gets in Emacs. Hash tables, though O(1),
impose a minimum threshold of overhead before it becomes the efficient
option, but this benefit won't be obvious for datasets of at least 60 or
less.

Since modulep! is used *a lot*, and used to determine a module's
state (and state of its flags), there is a benefit to caching it.
Still, this is only a read-only cache, and does not replace the
`doom-modules` hash-table, which will always be the preferred interface
for the rest of the module API.
This commit is contained in:
Henrik Lissner 2022-09-12 23:44:04 +02:00
parent 7161f27bb3
commit c5188c4388
No known key found for this signature in database
GPG Key ID: B60957CA074D39A3
2 changed files with 17 additions and 7 deletions

View File

@ -47,6 +47,12 @@ hoist buggy forms into autoloads.")
(cl-loop for var in doom-autoloads-cached-vars
when (boundp var)
collect `(set ',var ',(symbol-value var)))
;; Cache module state and flags in symbol plists for quick lookup by
;; `modulep!' later.
(cl-loop for (category . modules) in (seq-group-by #'car (doom-module-list))
collect `(setplist ',category
(quote ,(cl-loop for (_ . module) in modules
nconc `(,module ,(get category module))))))
(doom-autoloads--scan
(append (doom-glob doom-core-dir "lib/*.el")
(cl-loop for dir

View File

@ -107,7 +107,7 @@ symbols, and that module's plist."
(declare (pure t) (side-effect-free t))
(lambda (module plist)
(let ((doom--current-module module)
(doom--current-flags (plist-get plist :flags))
(doom--current-flags (cdr (get (car module) (cdr module))))
(inhibit-redisplay t))
(load! file (plist-get plist :path) t))))
@ -178,6 +178,11 @@ following properties:
Example:
(doom-module-set :lang 'haskell :flags '(+lsp))"
;; Doom caches flags and features using symbol plists for fast lookups in
;; `modulep!'. plists lack the overhead, and are much faster for datasets this
;; small. The format of this case is (cons FEATURES FLAGS)
(put category module (cons t (plist-get plist :flags)))
;; But the hash table will always been Doom's formal storage for modules.
(puthash (cons category module) plist doom-modules))
(defun doom-module-expand-path (category module &optional file)
@ -561,15 +566,14 @@ Module FLAGs are set in your config's `doom!' block, typically in
CATEGORY and MODULE can be omitted When this macro is used from inside a module
(except your DOOMDIR, which is a special module). e.g. (modulep! +flag)"
(and (cond (flag (memq flag (doom-module-get category module :flags)))
(module (doom-module-p category module))
(and (cond (flag (memq flag (cdr (get category module))))
(module (get category module))
(doom--current-flags (memq category doom--current-flags))
(doom--current-module
(memq category (doom-module-get (car doom--current-module)
(cdr doom--current-module)
:flags)))
(memq category (cdr (get (car doom--current-module)
(cdr doom--current-module)))))
((if-let (module (doom-module-from-path (macroexpand '(file!))))
(memq category (doom-module-get (car module) (cdr module) :flags))
(memq category (cdr (get (car module) (cdr module))))
(error "(modulep! %s %s %s) couldn't figure out what module it was called from (in %s)"
category module flag (file!)))))
t))