aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2021-08-14 01:06:19 +0100
committerJoão Távora2021-08-14 01:28:03 +0100
commit32469a19c620bcaddc2f3e0e590de827014fd21f (patch)
treec04b838cfce37e647762241d9ed932699d313b22
parent254dc6ab4ca8e6a549a795f9eaf45378ce51b61f (diff)
downloademacs-scratch/icomplete-lazy-highlight-attempt.tar.gz
emacs-scratch/icomplete-lazy-highlight-attempt.zip
Attempt to speed up completion with lazy highlightingscratch/icomplete-lazy-highlight-attempt
After enabling fido-mode and replacing the while-no-input in icomplete.el with benchmark-progn, evaluated this form: (completing-read "bla" obarray) many times in my lightly loaded Emacs session which has: (length (all-completions "" obarray)) = 46762 symbols On every evaluation, a measurement of the time it takes to generate completions is taken and printed to *Messages*. These are the results. They are decent but not spectacular. Can't seem to reproduce the spectacular results of https://debbugs.gnu.org/cgi/bugreport.cgi?bug=48841#83 WITH completion-pcm-lazy-hilit = nil Elapsed time: 0.830821s (0.652251s in 3 GCs) Elapsed time: 0.828888s (0.652339s in 3 GCs) Elapsed time: 0.840977s (0.665493s in 3 GCs) Elapsed time: 0.838810s (0.660840s in 3 GCs) Elapsed time: 0.844244s (0.666753s in 3 GCs) Elapsed time: 0.837558s (0.649146s in 3 GCs) Elapsed time: 0.860952s (0.680139s in 3 GCs) Elapsed time: 0.835933s (0.657953s in 3 GCs) Elapsed time: 0.833641s (0.660285s in 3 GCs) Elapsed time: 0.612756s (0.441977s in 2 GCs) Average: 0.816s WITH completion-pcm-lazy-hilit = t Elapsed time: 0.618526s (0.446630s in 9 GCs) Elapsed time: 0.519817s (0.342596s in 5 GCs) Elapsed time: 0.580578s (0.404180s in 5 GCs) Elapsed time: 0.535658s (0.362378s in 4 GCs) Elapsed time: 0.598076s (0.424361s in 3 GCs) Elapsed time: 0.613332s (0.447435s in 3 GCs) Elapsed time: 0.510226s (0.338068s in 2 GCs) Elapsed time: 0.706932s (0.534357s in 3 GCs) Elapsed time: 0.565533s (0.392478s in 2 GCs) Elapsed time: 0.566993s (0.398196s in 2 GCs) Average: 0.582s * lisp/icomplete.el (icomplete-exhibit) (icomplete--render-vertical) (icomplete--render-vertical): (icomplete-completions): Use completion-pcm-lazy-hilit. * lisp/minibuffer.el (completion-pcm-lazy-hilit): New function and flag. (completion-pcm--hilit-commonality) Use it.
-rw-r--r--lisp/icomplete.el10
-rw-r--r--lisp/minibuffer.el46
2 files changed, 43 insertions, 13 deletions
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index adea1505fd2..c6ce3efb6d9 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -683,6 +683,7 @@ See `icomplete-mode' and `minibuffer-setup-hook'."
683 ;; deterministic but `C-x C-f M-DEL M-DEL ...' 683 ;; deterministic but `C-x C-f M-DEL M-DEL ...'
684 ;; seems to trigger it fairly often! 684 ;; seems to trigger it fairly often!
685 (while-no-input-ignore-events '(selection-request)) 685 (while-no-input-ignore-events '(selection-request))
686 (completion-pcm-lazy-hilit t)
686 (text (while-no-input 687 (text (while-no-input
687 (icomplete-completions 688 (icomplete-completions
688 field-string 689 field-string
@@ -797,7 +798,9 @@ Return a list of (COMP PREFIX SUFFIX)."
797 (cl-return-from icomplete--render-vertical 798 (cl-return-from icomplete--render-vertical
798 (concat 799 (concat
799 " \n" 800 " \n"
800 (mapconcat #'identity torender icomplete-separator)))) 801 (mapconcat #'identity
802 (mapcar #'completion-pcm-lazy-hilit torender)
803 icomplete-separator))))
801 for (comp prefix) in triplets 804 for (comp prefix) in triplets
802 maximizing (length prefix) into max-prefix-len 805 maximizing (length prefix) into max-prefix-len
803 maximizing (length comp) into max-comp-len 806 maximizing (length comp) into max-comp-len
@@ -809,7 +812,7 @@ Return a list of (COMP PREFIX SUFFIX)."
809 (cl-loop for (comp prefix suffix) in triplets 812 (cl-loop for (comp prefix suffix) in triplets
810 concat prefix 813 concat prefix
811 concat (make-string (- max-prefix-len (length prefix)) ? ) 814 concat (make-string (- max-prefix-len (length prefix)) ? )
812 concat comp 815 concat (completion-pcm-lazy-hilit comp)
813 concat (make-string (- max-comp-len (length comp)) ? ) 816 concat (make-string (- max-comp-len (length comp)) ? )
814 concat suffix 817 concat suffix
815 concat icomplete-separator)))) 818 concat icomplete-separator))))
@@ -959,7 +962,8 @@ matches exist."
959 (if (< prospects-len prospects-max) 962 (if (< prospects-len prospects-max)
960 (push comp prospects) 963 (push comp prospects)
961 (setq limit t))) 964 (setq limit t)))
962 (setq prospects (nreverse prospects)) 965 (setq prospects
966 (nreverse (mapcar #'completion-pcm-lazy-hilit prospects)))
963 ;; Decorate first of the prospects. 967 ;; Decorate first of the prospects.
964 (when prospects 968 (when prospects
965 (let ((first (copy-sequence (pop prospects)))) 969 (let ((first (copy-sequence (pop prospects))))
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 1e8e9fc6246..21d194b7bdc 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3512,6 +3512,24 @@ one large \"hole\" and a clumped-together \"oo\" match) higher
3512than the latter (which has two \"holes\" and three 3512than the latter (which has two \"holes\" and three
3513one-letter-long matches).") 3513one-letter-long matches).")
3514 3514
3515(defvar completion-pcm-lazy-hilit nil
3516 "If non-nil, defer highting of matching completions to frontend.
3517The completion frontend may bind this variable around
3518completion-generating calls and then be responsible for calling
3519the function `completion-pcm-lazy-hilit' on each completion that
3520it intends to actually display to the user. This enables the
3521`completion-pcm' backend to skip expensive string copies.")
3522
3523(defun completion-pcm-lazy-hilit (str)
3524 "Hilit STR completion produced under `completion-pcm-lazy-hilit'.
3525Return a copy of STR that can be display to the user. If STR,
3526was not produced under `completion-pcm-lazy-hilit', it is assumed
3527to be hilighted and unchanged."
3528 (let ((str (copy-sequence str)))
3529 (dolist (v (get-text-property 0 'completion-pcm-lazy-hilit str))
3530 (add-face-text-property (car v) (cadr v) (caddr v) nil str))
3531 str))
3532
3515(defun completion-pcm--hilit-commonality (pattern completions) 3533(defun completion-pcm--hilit-commonality (pattern completions)
3516 "Show where and how well PATTERN matches COMPLETIONS. 3534 "Show where and how well PATTERN matches COMPLETIONS.
3517PATTERN, a list of symbols and strings as seen 3535PATTERN, a list of symbols and strings as seen
@@ -3527,8 +3545,10 @@ between 0 and 1, and with faces `completions-common-part',
3527 last-md) 3545 last-md)
3528 (mapcar 3546 (mapcar
3529 (lambda (str) 3547 (lambda (str)
3530 ;; Don't modify the string itself. 3548 (unless completion-pcm-lazy-hilit
3531 (setq str (copy-sequence str)) 3549 ;; Don't modify the string itself.
3550 (setq str (copy-sequence str))
3551 (put-text-property 0 1 'completion-pcm-lazy-hilit nil str))
3532 (unless (string-match re str) 3552 (unless (string-match re str)
3533 (error "Internal error: %s does not match %s" re str)) 3553 (error "Internal error: %s does not match %s" re str))
3534 (let* ((pos (if point-idx (match-beginning point-idx) (match-end 0))) 3554 (let* ((pos (if point-idx (match-beginning point-idx) (match-end 0)))
@@ -3573,12 +3593,22 @@ between 0 and 1, and with faces `completions-common-part',
3573 (score-numerator 0) 3593 (score-numerator 0)
3574 (score-denominator 0) 3594 (score-denominator 0)
3575 (last-b 0) 3595 (last-b 0)
3596 (hilit-maybe
3597 (lambda (from to face)
3598 (cond ((< (length str) to) nil)
3599 (completion-pcm-lazy-hilit
3600 (let ((lazies (get-text-property
3601 0 'completion-pcm-lazy-hilit str)))
3602 (put-text-property 0 1 'completion-pcm-lazy-hilit
3603 (cons (list from to face)
3604 lazies)
3605 str)))
3606 (t
3607 (add-face-text-property from to face nil str)))))
3576 (update-score-and-face 3608 (update-score-and-face
3577 (lambda (a b) 3609 (lambda (a b)
3578 "Update score and face given match range (A B)." 3610 "Update score and face given match range (A B)."
3579 (add-face-text-property a b 3611 (funcall hilit-maybe a b 'completions-common-part)
3580 'completions-common-part
3581 nil str)
3582 (setq 3612 (setq
3583 score-numerator (+ score-numerator (- b a))) 3613 score-numerator (+ score-numerator (- b a)))
3584 (unless (or (= a last-b) 3614 (unless (or (= a last-b)
@@ -3601,11 +3631,7 @@ between 0 and 1, and with faces `completions-common-part',
3601 ;; for that extra bit of match (bug#42149). 3631 ;; for that extra bit of match (bug#42149).
3602 (unless (= from match-end) 3632 (unless (= from match-end)
3603 (funcall update-score-and-face from match-end)) 3633 (funcall update-score-and-face from match-end))
3604 (if (> (length str) pos) 3634 (funcall hilit-maybe pos (1+ pos) 'completions-first-difference)
3605 (add-face-text-property
3606 pos (1+ pos)
3607 'completions-first-difference
3608 nil str))
3609 (unless (zerop (length str)) 3635 (unless (zerop (length str))
3610 (put-text-property 3636 (put-text-property
3611 0 1 'completion-score 3637 0 1 'completion-score