Subject: Re: bug#78520: 31.0.50; Performance issue in dired+isearch with dired-isearch-filenames

From: Eli Zaretskii <[email-masked]>
Date: Thu, 22 May 2025 10:41:21 +0300

> From: Juri Linkov <[email-masked]>
> Cc: [email-masked],  [email-masked]
> Date: Thu, 22 May 2025 09:33:20 +0300
> 
> >> When you customize `dired-isearch-filenames` to non-nil, it uses
> >> `next-single-property-change` to restrict matches to filenames.
> >
> > I guess this could be slow in a buffer with a lot of properties?
> 
> In a Dired buffer the property 'dired-filename' is almost on every line.
> 
> > Would it be possible to speed this up by searching as usual, but then
> > rejecting matches whose positions don't have the 'filename' property?
> > Or was this tried and found to be not faster?
> 
> The currently implementation was intended to be quite fast,
> and indeed when I try it on a dir with thousands of files,
> isearch-lazy-highlight takes only 1 sec, even with thousands of matches.
> But apparently on slower hardware it's more slow.

I have fast hardware, but C-s for a match near the end of a Dired
buffer showing 5K files takes about 9 sec.  This is in an unoptimized
build; an optimized build still takes 2.25 sec.

I'm not sure why you are talking about isearch-lazy-highlight, that's
not what the original report is about.  C-s is slow even if I turn off
isearch-lazy-highlight, and the profile below in that case still
points to next-single-property-change as the hot spot.

> So unless someone wants to make an effort to optimize the
> implementation more, IMHO this could be closed.

Does isearch.el have some infrastructure for examining a match and
rejecting it if it doesn't meet some criteria?  If so, can you point
me to that infrastructure?

Here's the profile I collected after turning off
isearch-lazy-highlight:

         621  87% - ...
         618  87%  - isearch-search
         618  87%   - condition-case
         618  87%    - let
         618  87%     - while
         618  87%      - setq
         618  87%       - isearch-search-string
         618  87%        - let*
         618  87%         - save-excursion
         618  87%          - funcall
         618  87%           - #<byte-code-function 21A>
         618  87%            - apply
         618  87%             - search-within-boundaries
         618  87%              - let*
         618  87%               - while
         311  43%                - setq
         311  43%                 - funcall
         311  43%                  - #<interpreted-function E6E>
         311  43%                   - let
         311  43%                    - if
         311  43%                     - mapcar
         308  43%                      - #<interpreted-function D88>
         308  43%                         next-single-property-change
           3   0%                      - function
           3   0%                       - cconv-make-interpreted-closure
           2   0%                          cconv-fv
           1   0%                          macroexpand-all
         307  43%                - if
         303  42%                 - setq
         302  42%                  - funcall
         299  42%                   - #<interpreted-function E6E>
         299  42%                    - let
         298  42%                     - if
         298  42%                      - mapcar
         289  40%                       - #<interpreted-function 740>
         289  40%                          next-single-property-change
           8   1%                       - function
           8   1%                        - cconv-make-interpreted-closure
           3   0%                         - macroexpand-all
           3   0%                          - macroexp--expand-all
           3   0%                           - macroexp--all-forms
           2   0%                            - macroexp--expand-all
           2   0%                             - #<byte-code-function 83C>
           2   0%                              - macroexp--all-forms
           2   0%                               - macroexp--expand-all
           2   0%                                  macroexp-macroexpand
           3   0%                         - cconv-fv
           2   0%                            mapcar
           1   0%                          - cconv-analyze-form
           1   0%                           - cconv--analyze-function
           1   0%                            - mapcar
           1   0%                               #<byte-code-function F28>
           3   0%                   - #<interpreted-function FDE>
           2   0%                    - let
           1   0%                     - funcall
           1   0%                        re-search-forward
           1   0%                       cond
           4   0%                 - if
           3   0%                  - progn
           3   0%                   - if
           2   0%                      goto-char
           2   0%  - completion-try-completion
           2   0%   - completion--nth-completion
           2   0%    - seq-some
           2   0%     - seq-do
           2   0%      - mapc
           2   0%       - #<byte-code-function B6E>
           2   0%        - #<byte-code-function BF2>
           2   0%         - eval
           2   0%          - let
           2   0%           - funcall
           2   0%            - #<byte-code-function C44>
           1   0%             - completion-pcm-try-completion
           1   0%              - completion-pcm--find-all-completions
           1   0%               - completion-pcm--all-completions
           1   0%                - all-completions
           1   0%                 - #<byte-code-function AA0>
           1   0%                  - complete-with-action
           1   0%                     all-completions
           1   0%             - completion-basic-try-completion
           1   0%              - try-completion
           1   0%               - #<byte-code-function AA0>
           1   0%                - complete-with-action
           1   0%                   try-completion
           1   0%  - funcall-interactively
           1   0%   - isearch-printing-char
           1   0%    - let
           1   0%     - if
           1   0%      - isearch-process-search-char
           1   0%       - let*
           1   0%        - isearch-process-search-string
           1   0%         - isearch-search-and-update
           1   0%          - isearch-update
           1   0%           - if
           1   0%            - progn
           1   0%             - if
           1   0%              - let
           1   0%               - setq
           1   0%                - pos-visible-in-window-group-p
           1   0%                   pos-visible-in-window-p
          68   9%   Automatic GC
          14   1% - command-execute
          14   1%  - call-interactively
          14   1%   - byte-code
          14   1%    - read-extended-command
          14   1%     - read-extended-command-1
          14   1%      - completing-read
          14   1%       - completing-read-default
          14   1%        - read-from-minibuffer
           2   0%           redisplay_internal (C function)
           6   0%   redisplay_internal (C function)