Subject: Re: bug#78545: 31.0.50; project-mode-line is slow because it tries to read files on each update

From: Daniel Colascione <[email-masked]>
Date: Thu, 22 May 2025 11:53:57 -0400

On May 22, 2025 7:47:18 AM EDT, Ship Mints <[email-masked]> wrote:
>On Thu, May 22, 2025 at 2:17 AM Yikai Zhao <[email-masked]> wrote:
>
>> After enabling `project-mode-line`, I find my emacs slightly less
>> responsive. I think it's because project-mode-line is slow due to
>> it trying to read files on each update. Here's how I reproduce it:
>>
>> - Run `emacs -Q`
>> - Evaluate `(setopt project-mode-line t)`
>> - Open some random file in a non-project directory, e.g. `/tmp/test`,
>> start typing
>>
>> Here's part of the profiling result:
>>
>>          114  62% - redisplay_internal (C function)
>>           42  23%  - eval
>>           41  22%   - project-mode-line-format
>>           41  22%    - project-current
>>           41  22%     - project--find-in-directory
>>           41  22%      - run-hook-with-args-until-success
>>           41  22%       - project-try-vc
>>           41  22%        - project-try-vc--search
>>           25  13%         - project--value-in-dir
>>           22  12%          - hack-dir-local-variables
>>           22  12%           - #<byte-code-function 24E>
>>           22  12%            - hack-dir-local--get-variables
>>           22  12%             - dir-locals-find-file
>>           22  12%              - locate-dominating-file
>>           12   6%               + abbreviate-file-name
>>            3   1%          + #<byte-code-function 98F>
>>           13   7%         - locate-dominating-file
>>            6   3%          + #<byte-code-function 4D9>
>>            3   1%            abbreviate-file-name
>>            3   1%
>>
>> It shows that `project-mode-line-format` can take a significant portion
>> of the redisplay time. It increases even more when the directory is deep
>> or the disk is slow.
>>
>> IMO the performance of this function should be improved.
>>
>> I have two questions:
>>
>> 1. Is it possible to simply cache the result as buffer-local?
>> 2. IIUC some of the file reading comes from `project--value-in-dir`,
>> which opens a temporary buffer to load dir local variables. Why doesn't
>> it simply read the variable value in the current buffer?
>>
>
>I've advised project functions to cache the "invariants" current project
>and project root to incur these costs once per buffer.  I also cache the
>nuance of a "non project" to avoid repeated project probing on buffers that
>don't have a project.
>
>I thought maybe I was the only person silly enough to invoke costly project
>functions for every tab in `tab-bar` and every mode-line update.
>
>I could contribute optional caching to project.el if there is sufficient
>demand for it.  Unless someone else wants to.

We could also just have the IO functions signal error if called during a mode line update.