diff --git a/lisp/org-persist.el b/lisp/org-persist.el index 9521f86a1..b16289da7 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)