On Thu, May 22, 2025 at 2:17 AM Yikai Zhao <yikai@z1k.dev> 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.