branch: externals/org commit f77800c68b69f770886b9c103a101550ec530896 Author: Ihor Radchenko <yanta...@gmail.com> Commit: Ihor Radchenko <yanta...@gmail.com>
org-persist: Avoid overwriting / re-reading unchanged persisted data * lisp/org-persist.el (org-persist--read-cache): (org-persist--write-cache): New variables holding previously written / read data. (org-persist-read): Avoid re-reading data from FS when the writing has been performed in the same Emacs session. (org-persist-write): Do not overwrite unchanged data. --- lisp/org-persist.el | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/lisp/org-persist.el b/lisp/org-persist.el index 9521f86a1b..b16289da72 100644 --- a/lisp/org-persist.el +++ b/lisp/org-persist.el @@ -749,6 +749,14 @@ When ASSOCIATED is `all', unregister CONTAINER everywhere." (remove container (plist-get collection :container))) (org-persist--add-to-index collection)))))) +(defvar org-persist--read-cache (make-hash-table :test #'equal) + "Hash table storing as-read data object hashes. + +This data is used to avoid overwriting unchanged data.") +(defvar org-persist--write-cache (make-hash-table :test #'equal) + "Hash table storing as-written data objects. + +This data is used to avoid reading the data multiple times.") (defun org-persist-read (container &optional associated hash-must-match load?) "Restore CONTAINER data for ASSOCIATED. When HASH-MUST-MATCH is non-nil, do not restore data if hash for @@ -783,15 +791,18 @@ When LOAD? is non-nil, load the data instead of reading." (unless (seq-find (lambda (v) (run-hook-with-args-until-success 'org-persist-before-read-hook v associated)) (plist-get collection :container)) - (setq data (org-persist--read-elisp-file persist-file)) - (cl-loop for container in (plist-get collection :container) - with result = nil - do - (if load? - (push (org-persist-load:generic container (alist-get container data nil nil #'equal) collection) result) - (push (org-persist-read:generic container (alist-get container data nil nil #'equal) collection) result)) - (run-hook-with-args 'org-persist-after-read-hook container associated) - finally return (if (= 1 (length result)) (car result) result))))))) + (setq data (or (gethash persist-file org-persist--write-cache) + (org-persist--read-elisp-file persist-file))) + (puthash persist-file (sxhash-equal data) org-persist--read-cache) + (when data + (cl-loop for container in (plist-get collection :container) + with result = nil + do + (if load? + (push (org-persist-load:generic container (alist-get container data nil nil #'equal) collection) result) + (push (org-persist-read:generic container (alist-get container data nil nil #'equal) collection) result)) + (run-hook-with-args 'org-persist-after-read-hook container associated) + finally return (if (= 1 (length result)) (car result) result)))))))) (defun org-persist-load (container &optional associated hash-must-match) "Load CONTAINER data for ASSOCIATED. @@ -847,7 +858,9 @@ When IGNORE-RETURN is non-nil, just return t on success without calling (let ((file (org-file-name-concat org-persist-directory (plist-get collection :persist-file))) (data (mapcar (lambda (c) (cons c (org-persist-write:generic c collection))) (plist-get collection :container)))) - (org-persist--write-elisp-file file data) + (puthash file data org-persist--write-cache) + (unless (equal (sxhash-equal data) (gethash file org-persist--read-cache)) + (org-persist--write-elisp-file file data)) (or ignore-return (org-persist-read container associated)))))))) (defun org-persist-write-all (&optional associated)