diff options
| author | João Távora | 2021-08-14 01:06:19 +0100 |
|---|---|---|
| committer | João Távora | 2021-08-14 01:28:03 +0100 |
| commit | 32469a19c620bcaddc2f3e0e590de827014fd21f (patch) | |
| tree | c04b838cfce37e647762241d9ed932699d313b22 | |
| parent | 254dc6ab4ca8e6a549a795f9eaf45378ce51b61f (diff) | |
| download | emacs-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.el | 10 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 46 |
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 | |||
| 3512 | than the latter (which has two \"holes\" and three | 3512 | than the latter (which has two \"holes\" and three |
| 3513 | one-letter-long matches).") | 3513 | one-letter-long matches).") |
| 3514 | 3514 | ||
| 3515 | (defvar completion-pcm-lazy-hilit nil | ||
| 3516 | "If non-nil, defer highting of matching completions to frontend. | ||
| 3517 | The completion frontend may bind this variable around | ||
| 3518 | completion-generating calls and then be responsible for calling | ||
| 3519 | the function `completion-pcm-lazy-hilit' on each completion that | ||
| 3520 | it 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'. | ||
| 3525 | Return a copy of STR that can be display to the user. If STR, | ||
| 3526 | was not produced under `completion-pcm-lazy-hilit', it is assumed | ||
| 3527 | to 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. |
| 3517 | PATTERN, a list of symbols and strings as seen | 3535 | PATTERN, 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 |