emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/org 8f39743 16/41: Use cache in org-up-heading-safe


From: ELPA Syncer
Subject: [elpa] externals/org 8f39743 16/41: Use cache in org-up-heading-safe
Date: Sun, 16 May 2021 04:57:18 -0400 (EDT)

branch: externals/org
commit 8f39743ce69c3d68600627d8732bd6a7b8734208
Author: Ihor Radchenko <yantar92@gmail.com>
Commit: Bastien <bzg@gnu.org>

    Use cache in org-up-heading-safe
    
    * lisp/org.el (org-up-heading-safe): Use buffer-local cache to store
    positions of parent headings.  The cache is invalidated when buffer
    text is changed, according to `buffer-chars-modified-tick'.
    (org--up-heading-cache):  Buffer-local hash-table storing the cache.
    (org--up-heading-cache-tick):  The buffer modification state for
    currently active `org--up-heading-cache'.
    
    The optimisation is critical when running agenda or org-entry-get
    queries using property/tag inheritance.  In such scenarios
    `org-up-heading-safe' can be called thousands of times.  For example,
    building todo agenda on large number of headings lead to the following
    benchmark results:
    
    Benchmark:
    
    1. (elp-instrument-function #'org-up-heading-safe)
    2. Run agenda
    3. (elp-results) ;; function, # calls, total time, avg time
    
    Without cache:
    org-up-heading-safe  27555       8.4234025759  0.0003056941
    
    With cache, first run:
    org-up-heading-safe  23227       0.5300747539  2.282...e-05
    
    With cache, second run on unchanged buffer:
    org-up-heading-safe  23227       0.1447754880  6.233...e-06
    
    The final speedup is 1-2 orders of magnitude (~15-56 times).
---
 lisp/org.el | 30 ++++++++++++++++++++++++++----
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 04abb73..a30dbed 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -20460,6 +20460,10 @@ This function considers both visible and invisible 
heading lines.
 With argument, move up ARG levels."
   (outline-up-heading arg t))
 
+(defvar-local org--up-heading-cache nil
+  "Buffer-local `org-up-heading-safe' cache.")
+(defvar-local org--up-heading-cache-tick nil
+  "Buffer `buffer-chars-modified-tick' in `org--up-heading-cache'.")
 (defun org-up-heading-safe ()
   "Move to the heading line of which the present line is a subheading.
 This version will not throw an error.  It will return the level of the
@@ -20469,10 +20473,28 @@ Also, this function will be a lot faster than 
`outline-up-heading',
 because it relies on stars being the outline starters.  This can really
 make a significant difference in outlines with very many siblings."
   (when (ignore-errors (org-back-to-heading t))
-    (let ((level-up (1- (funcall outline-level))))
-      (and (> level-up 0)
-          (re-search-backward (format "^\\*\\{1,%d\\} " level-up) nil t)
-          (funcall outline-level)))))
+    (let (level-cache)
+      (unless org--up-heading-cache
+        (setq org--up-heading-cache (make-hash-table)))
+      (if (and (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
+               (setq level-cache (gethash (point) org--up-heading-cache)))
+          (when (<= (point-min) (car level-cache) (point-max))
+            ;; Parent is inside accessible part of the buffer.
+            (progn (goto-char (car level-cache))
+                   (cdr level-cache)))
+        ;; Buffer modified.  Invalidate cache.
+        (unless (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
+          (setq-local org--up-heading-cache-tick
+                      (buffer-chars-modified-tick))
+          (clrhash org--up-heading-cache))
+        (let* ((level-up (1- (funcall outline-level)))
+               (pos (point))
+               (result (and (> level-up 0)
+                           (re-search-backward
+                             (format "^\\*\\{1,%d\\} " level-up) nil t)
+                           (funcall outline-level))))
+          (when result (puthash pos (cons (point) result) 
org--up-heading-cache))
+          result)))))
 
 (defun org-up-heading-or-point-min ()
   "Move to the heading line of which the present is a subheading, or point-min.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]