Subject: 30.0.91; (documentation 'pcase) can take several seconds

From: Yikai Zhao <[email-masked]>
Date: Sat, 12 Oct 2024 16:02:04 +0800

When `lsp-mode` is loaded, `(documentation 'pcase)` can take several
seconds to complete.

Apparently, it would iterate over all defined pcase macros (N), and for
each of those, `help-fns-short-filename` would iterate over all items in
`load-path` (M). Total time complexity is N*M.

In my case, N is about ~400 (defined in lsp-protocols.el) and M is about
~100 (I think it's a normal case?).

This is especially problematic since the `documentation` method can be
invoked by eldoc, which affects the responsiveness during editing.

--

Here's my profiler result:

        2713  86% - timer-event-handler
        2713  86%  - apply
        2707  86%   - #<native-comp-function
F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_12>
        2707  86%    - eldoc-print-current-symbol-info
        2707  86%     - eldoc--invoke-strategy
        2707  86%      - eldoc-documentation-default
        2707  86%       - #<native-comp-function
F616e6f6e796d6f75732d6c616d626461_anonymous_lambda_17>
        2707  86%        - elisp-eldoc-funcall
        2707  86%         - elisp-get-fnsym-args-string
        2707  86%          - documentation
        2707  86%           - pcase--make-docstring
        2606  82%            - help-fns-short-filename
        2598  82%             - file-relative-name
         335  10%                file-remote-p
          27   0%                string-prefix-p

--

In GNU Emacs 30.0.91 (build 1, x86_64-pc-linux-gnu, GTK+ Version
 3.22.30, cairo version 1.15.10) of 2024-09-12 built on 8afcf8f014b8
Repository revision: 9a1c76bf7ff49d886cc8e1a3f360d71e62544802
Repository branch: HEAD
Windowing system distributor 'The X.Org Foundation', version 11.0.12101004
System Description: Ubuntu 22.04.5 LTS

Configured using:
 'configure --prefix=/work/dist/AppDir --disable-locallisppath
 --with-native-compilation=aot --with-json --with-threads --with-sqlite3
 --with-tree-sitter --with-dbus --with-xml2 --with-modules --with-libgmp
 --with-gpm --with-lcms2 --with-mps --with-x --without-pgtk
 --without-gconf --with-x-toolkit=gtk3 --with-xft --without-tiff
 --without-imagemagick --with-gif --with-png --with-rsvg --with-webp
 --with-harfbuzz --with-cairo --with-libotf --without-m17n-flt
 --with-jpeg emacs_cv_jpeglib=/usr/lib/x86_64-linux-gnu/libjpeg.a
 CPPFLAGS=-I/work/dist/AppDir/include LDFLAGS=-L/work/dist/AppDir/lib'

Configured features:
CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LCMS2
LIBOTF LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG
SECCOMP SOUND SQLITE3 THREADS TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11
XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $EMACSDATA: /tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/etc
  value of $EMACSDOC: /tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/etc
  value of $EMACSLOADPATH: /tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp
  value of $EMACSPATH:
/tmp/.mount_emacsXLI1Nd/libexec/emacs/30.0.91/x86_64-pc-linux-gnu
  value of $LC_MONETARY: en_US.UTF-8
  value of $LC_NUMERIC: en_US.UTF-8
  value of $LC_TIME: en_US.UTF-8
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=fcitx
  locale-coding-system: utf-8-unix

Major mode: ELisp/l

Minor modes in effect:
  sudo-edit-indicator-mode: t
  evil-vimish-fold-mode: t
  vimish-fold-mode: t
  diff-hl-mode: t
  projectile-mode: t
  flycheck-posframe-mode: t
  flycheck-mode: t
  ligature-mode: t
  whitespace-mode: t
  electric-pair-mode: t
  hl-todo-mode: t
  dtrt-indent-mode: t
  windmove-mode: t
  tempel-abbrev-mode: t
  company-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  hl-line-mode: t
  display-line-numbers-mode: t
  recentf-mode: t
  pixel-scroll-precision-mode: t
  server-mode: t
  winner-mode: t
  global-auto-revert-mode: t
  save-place-mode: t
  vertico-mode: t
  which-key-mode: t
  global-evil-visualstar-mode: t
  evil-visualstar-mode: t
  evil-snipe-override-mode: t
  evil-snipe-override-local-mode: t
  evil-owl-mode: t
  global-evil-surround-mode: t
  evil-surround-mode: t
  evil-commentary-mode: t
  evil-mode: t
  evil-local-mode: t
  override-global-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  minibuffer-regexp-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/home/yikai/.emacs.d/lib/which-key/which-key hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/which-key
/home/yikai/.emacs.d/lib/transient/lisp/transient hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/transient
/home/yikai/.emacs.d/lib/editorconfig/editorconfig hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig
/home/yikai/.emacs.d/lib/editorconfig/editorconfig-tools hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig-tools
/home/yikai/.emacs.d/lib/editorconfig/editorconfig-fnmatch hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig-fnmatch
/home/yikai/.emacs.d/lib/editorconfig/editorconfig-core hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig-core
/home/yikai/.emacs.d/lib/editorconfig/editorconfig-core-handle hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig-core-handle
/home/yikai/.emacs.d/lib/editorconfig/editorconfig-conf-mode hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/editorconfig-conf-mode
/home/yikai/.emacs.d/lib/use-package/bind-key hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/bind-key
/home/yikai/.emacs.d/lib/use-package/use-package hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package
/home/yikai/.emacs.d/lib/use-package/use-package-lint hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-lint
/home/yikai/.emacs.d/lib/use-package/use-package-jump hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-jump
/home/yikai/.emacs.d/lib/use-package/use-package-ensure hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-ensure
/home/yikai/.emacs.d/lib/use-package/use-package-ensure-system-package
hides /tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-ensure-system-package
/home/yikai/.emacs.d/lib/use-package/use-package-diminish hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-diminish
/home/yikai/.emacs.d/lib/use-package/use-package-delight hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-delight
/home/yikai/.emacs.d/lib/use-package/use-package-core hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-core
/home/yikai/.emacs.d/lib/use-package/use-package-bind-key hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/use-package/use-package-bind-key
/home/yikai/.emacs.d/lib/compat/compat hides
/tmp/.mount_emacsXLI1Nd/share/emacs/30.0.91/lisp/emacs-lisp/compat

Features:
(shadow sort mail-extr emacsbug tramp-cmds loadhist doctor
devdocs-browser evil-collection-profiler profiler consult-xref
evil-collection-shortdoc shortdoc cus-start tabify descr-text
evil-collection-view view jka-compr evil-collection-woman woman
evil-collection-man man goto-addr magit-extras cl-print printing
ps-print ps-print-loaddefs lpr help-fns vc-hg vc-bzr vc-src vc-sccs
vc-svn vc-cvs vc-rcs evil-collection-vc-git vc-git bug-reference
magit-bookmark evil-collection-magit magit-submodule magit-blame
magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch
magit-clone magit-remote magit-commit magit-sequence magit-notes
magit-worktree magit-tag magit-merge magit-branch magit-reset
magit-files magit-refs magit-status magit evil-collection-package-menu
package url-handlers evil-collection-magit-repos magit-repos magit-apply
magit-wip magit-log jinja2-mode tramp-cache time-stamp bpftrace-mode
expand-region yaml-mode-expansions text-mode-expansions
cc-mode-expansions python-el-fgallina-expansions js-mode-expansions
html-mode-expansions css-mode-expansions er-basic-expansions
expand-region-core expand-region-custom pr-review-search css-mode
sgml-mode facemenu evil-collection-eww eww mm-url evil-collection-gnus
gnus nnheader range typescript-ts-mode sudo-edit ebuild-mode skeleton
autoinsert lsp-haskell haskell-mode haskell-cabal haskell-utils
haskell-font-lock haskell-indentation haskell-string
haskell-sort-imports haskell-lexeme haskell-align-imports
haskell-complete-module haskell-ghc-support flymake-proc
evil-collection-flymake flymake etags fileloop generator dabbrev
haskell-customize lsp-pyright lsp-mode lsp-protocol spinner lv inline ht
evil-vimish-fold vimish-fold f s git-gutter-fringe fringe-helper
git-gutter evil-collection-diff-hl diff-hl evil-collection-log-view
log-view evil-collection-vc-dir vc-dir ewoc vc vc-dispatcher projectile
evil-collection-grep grep ibuf-ext evil-collection-ibuffer ibuffer
ibuffer-loaddefs flycheck-posframe posframe flycheck-google-cpplint
evil-collection-flycheck flycheck ligature whitespace elec-pair hl-todo
dtrt-indent company-keywords company-dabbrev-code company-dabbrev
company-files make-mode evil-collection-sh-script sh-script executable
evil-collection-cmake-mode cmake-mode rst js c-ts-common
evil-collection-yaml-mode yaml-mode vertico-directory windmove tempel
company-abbrev company-emoji company-emoji-list company-capf company
orderless bazel evil-collection-xref xref which-func testcover
evil-collection-edebug edebug evil-collection-debug debug backtrace
evil-collection-python python treesit project evil-collection-imenu
imenu ffap protobuf-mode cc-mode cc-fonts cc-guess cc-menus cc-cmds
jsonnet-mode smie conf-mode url-queue textsec uni-scripts idna-mapping
ucs-normalize uni-confusable textsec-check pr-review pr-review-render
shr pixel-fill kinsoku url-file svg dom pr-review-action magit-diff
smerge-mode diff evil-collection-diff-mode diff-mode track-changes
git-commit evil-collection-log-edit log-edit message sendmail yank-media
evil-collection-dired dired dired-loaddefs rfc822 mml mml-sec
evil-collection-epa epa derived epg rfc6068 epg-config gnus-util
mm-decode mm-bodies mm-encode mailabbrev gmm-utils mailheader pcvs-util
add-log magit-core magit-autorevert magit-margin magit-transient
magit-process with-editor magit-mode transient browse-url benchmark
magit-git magit-base crm pr-review-input evil-collection-markdown-mode
markdown-mode evil-collection-outline noutline outline mule-util pulse
mail-utils network-stream url-cache hl-line display-line-numbers
pr-review-notification pr-review-listview pr-review-api ghub-graphql
treepy gsexp ghub url-http mail-parse rfc2231 rfc2047 rfc2045 mm-util
ietf-drums mail-prsvr url-gw nsm url-auth url url-proxy url-privacy
url-expand url-methods url-history url-cookie url-domsuf url-util
mailcap let-alist gnutls puny pr-review-common
evil-collection-magit-section magit-section dash recentf tree-widget
wid-edit evil-collection-consult consult cursor-sensor time pixel-scroll
cua-base auth-source-pass url-parse url-vars server fcitx dbus xml
winner evil-collection-vterm vterm evil-collection-bookmark bookmark pp
face-remap evil-collection-compile compile text-property-search
evil-collection-term term disp-table ehelp find-func vterm-module
term/xterm xterm cc-styles cc-align cc-engine cc-vars cc-defs
google-c-style midnight diary-lib diary-loaddefs
evil-collection-calendar cal-menu calendar cal-loaddefs autorevert
filenotify saveplace tramp-sh tramp trampver tramp-integration files-x
tramp-message tramp-compat xdg shell pcomplete evil-collection-comint
comint ansi-osc parse-time iso8601 time-date auth-source eieio
eieio-core password-cache json map ansi-color tramp-loaddefs cus-load
evil-collection-vertico vertico compat solarized-light-theme
solarized-theme solarized solarized-faces color
evil-collection-which-key which-key fringe-scale switch-buffer-functions
evil-visualstar evil-snipe evil-owl format-spec evil-surround
evil-commentary evil-commentary-integration
evil-collection-tabulated-list evil-collection-tab-bar
evil-collection-simple evil-collection-replace
evil-collection-process-menu evil-collection-kmacro evil-collection-info
evil-collection-indent evil-collection-help evil-collection-elisp-mode
evil-collection-eldoc evil-collection-buff-menu evil-collection annalist
evil evil-integration evil-maps evil-commands evil-digraphs reveal
evil-jumps evil-command-window evil-types evil-search evil-ex
evil-macros evil-repeat evil-states evil-core advice evil-common
thingatpt rect evil-vars ring edmacro kmacro byte-opt delight comp-run
use-package use-package-ensure use-package-delight use-package-diminish
use-package-bind-key bind-key easy-mmode use-package-core
yaml-mode-autoloads xonsh-mode-autoloads with-editor-autoloads
which-key-autoloads wgrep-autoloads vterm-autoloads vimrc-mode-autoloads
vimish-fold-autoloads vertico-autoloads use-package-autoloads
treesit-auto-autoloads treepy-autoloads transient-autoloads
tempel-autoloads switch-buffer-functions-autoloads suggest-autoloads
sudo-edit-autoloads spinner-autoloads solarized-theme-autoloads
s-autoloads rust-mode-autoloads rg-autoloads rainbow-mode-autoloads
pydoc-autoloads protobuf-mode-autoloads projectile-autoloads
pr-review-autoloads posframe-autoloads popup-autoloads
pkg-info-autoloads php-mode-autoloads package-lint-autoloads
org2elcomment-autoloads org-tree-slide-autoloads orderless-autoloads
markdown-mode-autoloads magit-autoloads lv-autoloads lua-mode-autoloads
lsp-pyright-autoloads lsp-mode-autoloads lsp-haskell-autoloads
loop-autoloads llama-autoloads ligature-autoloads kotlin-mode-autoloads
just-mode-autoloads jsonnet-mode-autoloads jinja2-mode-autoloads
ht-autoloads hl-todo-autoloads haskell-mode-autoloads
groovy-mode-autoloads gptel-autoloads goto-chg-autoloads
google-c-style-autoloads go-mode-autoloads gn-mode-autoloads
git-link-autoloads git-gutter-fringe-autoloads git-gutter-autoloads
ghub-autoloads fringe-helper-autoloads flycheck-posframe-autoloads
flycheck-package-autoloads flycheck-google-cpplint-autoloads
flycheck-autoloads fish-mode-autoloads fcitx-autoloads f-autoloads
explain-pause-mode-autoloads expand-region-autoloads
exec-path-from-shell-autoloads evil-visualstar-autoloads
evil-vimish-fold-autoloads evil-surround-autoloads evil-snipe-autoloads
evil-owl-autoloads evil-commentary-autoloads evil-collection-autoloads
evil-autoloads epl-autoloads epkg-autoloads embark-autoloads
emacsql-autoloads emacs-fringe-scale-autoloads editorconfig-autoloads
ebuild-mode-autoloads dumb-jump-autoloads dtrt-indent-autoloads
dockerfile-mode-autoloads diff-hl-autoloads devdocs-browser-autoloads
delight-autoloads dash-autoloads cuda-mode-autoloads copilot-autoloads
consult-flycheck-autoloads consult-autoloads compat-autoloads
company-emoji-autoloads company-autoloads codeium-autoloads cl-macs
cmake-mode-autoloads closql-autoloads bpftrace-mode-autoloads
borg-autoloads bazel-autoloads avy-autoloads annalist-autoloads
add-node-modules-path-autoloads borg loaddefs-gen generate-lisp-file
lisp-mnt radix-tree pcase info comp cl-seq comp-cstr cl-extra help-mode
comp-common warnings icons subr-x rx gv cl-loaddefs cl-lib bytecomp
byte-compile rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt
fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode
register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting cairo gtk x-toolkit xinput2 x multi-tty move-toolbar
make-network-process native-compile emacs)

Memory information:
((conses 16 1185831 1011558) (symbols 48 67125 23)
 (strings 32 316477 39434) (string-bytes 1 10307989)
 (vectors 16 123279) (vector-slots 8 2358285 658163)
 (floats 8 1093 15048) (intervals 56 31071 5410) (buffers 992 56))