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

From: Dmitry Gutov <[email-masked]>
Date: Mon, 7 Jun 2021 03:11:41 +0300

On 07.06.2021 02:49, João Távora wrote:

>     Same result, indeed. We should note, though, that
>     completion-pcm--hilit-commonality has some steps that were added
>     together with the 'flex' style, for it to work.
> 
> 
> But nothing algorithmically aberrant, I think.

Just some stuff adding work to GC, I think.

> By the way, I think you should be running benchmarks multiple times to 
> get times in the seconds range, and reduce noise. Multiple levels of CPU 
> cache and other factors like temp thottling may skew results when 
> running just one time.

Yeah, I repeat the action with each version for like a few dozen times, 
until I see the numbers stabilize, or just take the average.

>     Tried binding gc-cons-threshold to a high value, and even galling
>     garbage-collect-maybe (or not): that speeds it up, but adds some
>     unpredictable GC pauses later (though it would be nice to be able to
>     consolidate the pauses into one collection pass).
> 
> 
> Maybe in Elisp that's a good idea, in other lisps and other languages, 
> second-guessing the GC is a bad idea. I hear ours is so basic that 
> indeed it might be reasonable.

I never get good results with that.

>     Long story short, the patch I just installed, to reuse the match data,
>     brings the runtime down to
> 
>         Elapsed time: 0.066388s (0.050087s in 3 GCs)
> 
> 
> That's nice! but are you sure you're not seeing noise, too?

Pretty sure.

>     Tried other things like moving the update-score-and-face lambda out of
>     the mapcar loop - that didn't move a needle.
> 
> 
> If a lambda is non capturing of stuff inside the loop, only one copy of 
> it is ever made, I think. So it doesn't suprise me.

update-score-and-face references both variables in its closest binding 
form (score-numerator, score-denominator) and the parameter of its 
containing lambda (str).

Maybe moving all of them to parameters and return values (making it a 
static function and having the caller manage state) would help, I 
haven't tried that exactly.

>     And a weird part: replacing all repeated (length str) calls with a
>     reference to an existing local binding makes it *slower* (back to the
>     original performance).
> 
> 
> Might be noise, or you might be thrashing of CPU caches, who knows? If 
> the string length is on the same cache line as the contents of the 
> string you're reading, then evicting that to go read the value of a 
> boxed integer somewhere radically different is slow.

But the string value is boxed as well, right? So the code needs to 
follow one indirection either way. Perhaps there's also overhead in 
looking up the lexical scope.

I also tried using the new-and-shiny length> and length=. This simply 
made no measurable difference.

> Just speculation of 
> course. Might just be noise or something else entirely.

This is highly reproducible. On my machine, at least.

Given how weird it is, I wouldn't just write about it without 
recompiling, restarting Emacs and measuring the scenario several times, 
with different versions of code.