Ihor Radchenko <yanta...@posteo.net> writes: > I have addressed the poor performance of `file-truename' and > `find-buffer-visiting' in > https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=b7a737ef49e > That commit should be a part of Emacs 30.1 release, while you are on > Emacs 30.0.50 pre-release. Try to upgrade your emacs.
That looks great! I upgrade my emacs today and redo the test, it indeed makes a great speedup compare to before, see (1). I then wrote a draft patch (attached below) to cache the entry position to org-id-locations, which give a 10x speedup of org-id-find, see (2). Though the pure hashtable way is still faster, but now, I think, it's enough for me to use those new org-element-cache APIs. Thanks for the pointer! (1) Testing results before and after upgrade: before upgrade org-id-find 1000 6.4504779999 0.0064504779 org-entry-get 1000 0.0776989999 7.769...e-05 x/org-id-prop 1000 0.0090050000 9.005...e-06 after org-id-find 1000 1.8941470000 0.0018941470 org-entry-get 1000 0.1785620000 0.0001785620 x/org-id-prop 1000 0.0136359999 1.363...e-05 (2) org-id-find+org-element-cache: x/org-id-prop 9002 4.944075 0.0005492196 org-id-find 9002 3.9981600000 0.0004441413 org-entry-get 9005 3.4076170000 0.0003784138 org-element-cache-get-key 9002 0.8524290000 9.469...e-05 org-element-cache-store-key 2 0.000152 7.6e-05 Environment: Org mode version 9.8-pre (release_9.7.28-319-g24d155 @ ~/.emacs.d/org-mode/lisp/) GNU Emacs 31.0.50 (build 3, x86_64-w64-mingw32) of 2025-04-26
>From c4fed8529791f20e10c2119c6390bc6288c2a667 Mon Sep 17 00:00:00 2001 From: doerthous <doerth...@gmail.com> Date: Sat, 26 Apr 2025 14:31:40 +0800 Subject: [PATCH] org-id: Cache entry position. * org-id (org-id-find): cache entry position in org-id-locations. --- lisp/org-id.el | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/lisp/org-id.el b/lisp/org-id.el index 6ff63b295..4b3c159b3 100644 --- a/lisp/org-id.el +++ b/lisp/org-id.el @@ -396,15 +396,38 @@ With optional argument MARKERP, return the position as a new marker." (cond ((symbolp id) (setq id (symbol-name id))) ((numberp id) (setq id (number-to-string id)))) - (let ((file (org-id-find-id-file id)) - org-agenda-new-buffers where) - (when file - (setq where (org-id-find-id-in-file id file markerp))) + (let* ((loc (org-id--find-id-location id)) + (file (if (consp loc) (car loc) loc)) + (pos (if (consp loc) (cdr loc))) + org-agenda-new-buffers where buf) + (cond + ;; When loc is a cons cell, check whether it's valid or not. + ((consp loc) + (setq buf (or (find-buffer-visiting file) + (find-file-noselect file))) + (with-current-buffer buf + (when (equal (org-entry-get pos "ID") id) + ;; Make sure we're looking at entry's heading. + (org-with-wide-buffer + (goto-char pos) + (unless (org-at-heading-p) + (setq pos (org-back-to-heading-or-point-min) (point)))) + (setq where (if markerp + (move-marker (make-marker) pos buf) + (cons file pos)))))) + ((stringp file) + (setq where (org-id-find-id-in-file id file markerp)))) + (unless where (org-id-update-id-locations nil t) (setq file (org-id-find-id-file id)) (when file (setq where (org-id-find-id-in-file id file markerp)))) + + ;; Update id location cache. + (when (and where (or (not (consp loc)) (not (= (cdr loc) pos)))) + (setq loc (if markerp (cons file (marker-position where)) where)) + (puthash id loc org-id-locations)) where)) ;;; Internal functions @@ -660,9 +683,12 @@ If SILENT is non-nil, messages are suppressed." (defun org-id-hash-to-alist (hash) "Turn an org-id HASH into an alist. This is to be able to write it to a file." + ;; org-id-locations: hash, ID -> file or ID -> (file-name . point) + ;; .org-id-locations: alist, file-name -> IDs (let (res x) (maphash (lambda (k v) + (unless (stringp v) (setq v (car v))) (if (setq x (assoc v res)) (setcdr x (cons k (cdr x))) (push (list v k) res))) @@ -700,9 +726,10 @@ This is to be able to write it to a file." ;; Finding entries with specified id -;;;###autoload -(defun org-id-find-id-file (id) - "Query the id database for the file in which ID is located." +(defun org-id--find-id-location (id) + "Query the id database for the location in which ID is located. + +Return a filename or cons cell (file-name . position)." (unless org-id-locations (org-id-locations-load)) (or (and org-id-locations (hash-table-p org-id-locations) @@ -712,6 +739,12 @@ This is to be able to write it to a file." (buffer-file-name (or (buffer-base-buffer (current-buffer)) (current-buffer)))))) +;;;###autoload +(defun org-id-find-id-file (id) + "Query the id database for the file in which ID is located." + (let ((loc (org-id--find-id-location id))) + (if (stringp loc) loc (car loc)))) + (defun org-id-find-id-in-file (id file &optional markerp) "Return the position of the entry ID in FILE. -- 2.44.0.windows.1