Subject: Re: bug#48841: fido-mode is slower than ido-mode with similar settings

From: João Távora <[email-masked]>
Date: Sun, 13 Jun 2021 15:29:33 +0100

Dmitry Gutov <[email-masked]> writes:

> On 12.06.2021 02:24, João Távora wrote:
>> Dmitry Gutov <[email-masked]> writes:
>> 
>>> Looking forward for your analysis of fido-vertical-mode's performance
>>> improvement over the "normal" one.
>> So, I benchmarked before and after this patch to icomplete.el:
>>      diff --git a/lisp/icomplete.el b/lisp/icomplete.el
>>      index 08b4ef2030..3561ebfa04 100644
>>      --- a/lisp/icomplete.el
>>      +++ b/lisp/icomplete.el
>>      @@ -858,16 +858,8 @@ icomplete-completions
>>                      ;; removing making `comps' a proper list.
>>                      (base-size (prog1 (cdr last)
>>                                   (if last (setcdr last nil))))
>>      -               (most-try
>>      -                (if (and base-size (> base-size 0))
>>      -                    (completion-try-completion
>>      -                     name candidates predicate (length name) md)
>>      -                  ;; If the `comps' are 0-based, the result should be
>>      -                  ;; the same with `comps'.
>>      -                  (completion-try-completion
>>      -                   name comps nil (length name) md)))
>>      -               (most (if (consp most-try) (car most-try)
>>      -                       (if most-try (car comps) "")))
>>      +               (most-try nil)
>>      +               (most "")
>>                      ;; Compare name and most, so we can determine if name is
>>                      ;; a prefix of most, or something else.
>>                      (compare (compare-strings name nil nil
>
> All right, so this is not about try-completion, it's about
> completion-try-completion. That makes sense.

Yeah, to be honest, once I'm done actually using these functions I
immediately evict the differences between try-completion,
completion-try-completion, try-try-completion-completion, or any of
these yoda-speak variations from my mental cache.  

Here I meant is that there was something apparently useless and slow (to
fido-mode at least) going on in that else branch.

> Elapsed time: 0.329006s (0.246073s in 10 GCs)
>
> vs
>
> Elapsed time: 0.169200s (0.113762s in 5 GCs)
>
> I suppose the 40-70ms difference is due to delay in typing.

No idea.  In my (slower?) system, I typed C-u C-x C-e C-m pretty fast.
Presumably the C-m goes in before pp-eval-last-sexp has a chance to read
more input so I wouldn't think it's a delay in typing.  I could
investigate, but since your measurements confirm the same tendency
anyway, I think this simple patch is what's needed to close this issue.

diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 08b4ef2030..5d37f47e7d 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -859,13 +859,14 @@ icomplete-completions
                (base-size (prog1 (cdr last)
                             (if last (setcdr last nil))))
                (most-try
-                (if (and base-size (> base-size 0))
-                    (completion-try-completion
-                     name candidates predicate (length name) md)
-                  ;; If the `comps' are 0-based, the result should be
-                  ;; the same with `comps'.
-                  (completion-try-completion
-                   name comps nil (length name) md)))
+                (and (not fido-mode) ; Fido avoids these expensive calculations.
+                     (if (and base-size (> base-size 0))
+                         (completion-try-completion
+                          name candidates predicate (length name) md)
+                       ;; If the `comps' are 0-based, the result should be
+                       ;; the same with `comps'.
+                       (completion-try-completion
+                        name comps nil (length name) md))))
                (most (if (consp most-try) (car most-try)
                        (if most-try (car comps) "")))
                ;; Compare name and most, so we can determine if name is

João