From 3bb4ec9bb2ae503b059957e99234fb8155ca9857 Mon Sep 17 00:00:00 2001 From: Arnold Noronha Date: Sat, 2 May 2020 08:30:47 -0700 Subject: [PATCH] Avoid binding CASE-FOLD-SEARCH in tight loop IDO-IGNORE-ITEM-P is called for every buffer when switching buffers. However, that function binds CASE-FOLD-SEARCH, which appears to be an O(n) operation where n is (length (buffer-list)). So we avoid binding it if we know we don't need to as a workaround. To test this, this this: (loop for i from 0 to 6000 do (find-file (format "/tmp/xy%d.txt" i))) Then try switching buffers with and without this patch. --- lisp/ido.el | 67 ++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/lisp/ido.el b/lisp/ido.el index 81883402ad..a2394d1d37 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -3408,7 +3408,7 @@ ido-make-merged-file-list (defun ido-make-buffer-list-1 (&optional frame visible) "Return list of non-ignored buffer names." (delq nil - (mapcar + (mapcar (lambda (x) (let ((name (buffer-name x))) (if (not (or (ido-ignore-item-p name ido-ignore-buffers) (member name visible))) @@ -3823,36 +3823,41 @@ ido-ignore-item-p (and ido-process-ignore-lists re-list (save-match-data - (let ((ext-list (and ignore-ext ido-ignore-extensions - completion-ignored-extensions)) - (case-fold-search ido-case-fold) - ignorep nextstr - (flen (length name)) slen) - (while ext-list - (setq nextstr (car ext-list)) - (if (cond - ((stringp nextstr) - (and (>= flen (setq slen (length nextstr))) - (string-equal (substring name (- flen slen)) nextstr))) - ((functionp nextstr) (funcall nextstr name)) - (t nil)) - (setq ignorep t - ext-list nil - re-list nil) - (setq ext-list (cdr ext-list)))) - (while re-list - (setq nextstr (car re-list)) - (if (cond - ((stringp nextstr) (string-match nextstr name)) - ((functionp nextstr) (funcall nextstr name)) - (t nil)) - (setq ignorep t - re-list nil) - (setq re-list (cdr re-list)))) - ;; return the result - (if ignorep - (setq ido-ignored-list (cons name ido-ignored-list))) - ignorep))))) + (let ((inner (lambda () + (let ((ext-list (and ignore-ext ido-ignore-extensions + completion-ignored-extensions)) + ignorep nextstr + (flen (length name)) slen) + (while ext-list + (setq nextstr (car ext-list)) + (if (cond + ((stringp nextstr) + (and (>= flen (setq slen (length nextstr))) + (string-equal (substring name (- flen slen)) nextstr))) + ((functionp nextstr) (funcall nextstr name)) + (t nil)) + (setq ignorep t + ext-list nil + re-list nil) + (setq ext-list (cdr ext-list)))) + (while re-list + (setq nextstr (car re-list)) + (if (cond + ((stringp nextstr) (string-match nextstr name)) + ((functionp nextstr) (funcall nextstr name)) + (t nil)) + (setq ignorep t + re-list nil) + (setq re-list (cdr re-list)))) + ;; return the result + (if ignorep + (setq ido-ignored-list (cons name ido-ignored-list))) + ignorep)))) + + (if (eq case-fold-search ido-case-fold) + (funcall inner) + (let ((case-fold-search ido-case-fold)) + (funcall inner)))))))) ;; Private variable used by `ido-word-matching-substring'. (defvar ido-change-word-sub) -- 2.20.1