From 66d06261aaebf78708456d96001f016f94aec743 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Tue, 21 Jun 2022 23:19:09 +0200 Subject: [PATCH] perf(lib): factor seq out of fn! & bake in lookup table A little more time and space gained by cutting out seq entirely and pre-generating the argument lookup table. At least, in uncompiled use cases. The original implementation used regexp to lookup arguments, which was (relatively) expensive. By comparison, using `assq` is *much* faster, especially for datasets this small; and more so when I get around to byte-compiling Doom's core (assq has its own byte-compiler opcode). --- core/core-lib.el | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/core/core-lib.el b/core/core-lib.el index 40534e404..06de521cd 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -327,13 +327,15 @@ ARGLIST." (allow-other-keys arglist)) ,@body))) +(put 'doom--fn-crawl 'lookup-table + '((_ . 0) (_ . 1) (%2 . 2) (%3 . 3) (%4 . 4) + (%5 . 5) (%6 . 6) (%7 . 7) (%8 . 8) (%9 . 9))) (defun doom--fn-crawl (data args) (cond ((symbolp data) - (when-let* - ((lookup '(_ _ %2 %3 %4 %5 %6 %7 %8 %9)) - (pos (cond ((eq data '%*) 0) - ((memq data '(% %1)) 1) - ((cdr (assq data (seq-map-indexed #'cons lookup))))))) + (when-let + (pos (cond ((eq data '%*) 0) + ((memq data '(% %1)) 1) + ((cdr (assq data (get 'doom--fn-crawl 'lookup-table)))))) (when (and (= pos 1) (aref args 1) (not (eq data (aref args 1)))) @@ -342,8 +344,11 @@ ARGLIST." ((and (not (eq (car-safe data) '!)) (or (listp data) (vectorp data))) - (seq-doseq (elt data) - (doom--fn-crawl elt args))))) + (let ((len (length data)) + (i 0)) + (while (< i len) + (doom--fn-crawl (elt data i) args) + (cl-incf i)))))) (defmacro fn! (&rest args) "Return an lambda with implicit, positional arguments.