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.
This commit is contained in:
Ihor Radchenko 2022-06-21 09:35:01 +08:00
parent d687aa1786
commit f77800c68b
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
1 changed files with 23 additions and 10 deletions

View File

@ -749,6 +749,14 @@ When ASSOCIATED is `all', unregister CONTAINER everywhere."
(remove container (plist-get collection :container))) (remove container (plist-get collection :container)))
(org-persist--add-to-index collection)))))) (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?) (defun org-persist-read (container &optional associated hash-must-match load?)
"Restore CONTAINER data for ASSOCIATED. "Restore CONTAINER data for ASSOCIATED.
When HASH-MUST-MATCH is non-nil, do not restore data if hash for 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) (unless (seq-find (lambda (v)
(run-hook-with-args-until-success 'org-persist-before-read-hook v associated)) (run-hook-with-args-until-success 'org-persist-before-read-hook v associated))
(plist-get collection :container)) (plist-get collection :container))
(setq data (org-persist--read-elisp-file persist-file)) (setq data (or (gethash persist-file org-persist--write-cache)
(cl-loop for container in (plist-get collection :container) (org-persist--read-elisp-file persist-file)))
with result = nil (puthash persist-file (sxhash-equal data) org-persist--read-cache)
do (when data
(if load? (cl-loop for container in (plist-get collection :container)
(push (org-persist-load:generic container (alist-get container data nil nil #'equal) collection) result) with result = nil
(push (org-persist-read:generic container (alist-get container data nil nil #'equal) collection) result)) do
(run-hook-with-args 'org-persist-after-read-hook container associated) (if load?
finally return (if (= 1 (length result)) (car result) result))))))) (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) (defun org-persist-load (container &optional associated hash-must-match)
"Load CONTAINER data for ASSOCIATED. "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))) (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))) (data (mapcar (lambda (c) (cons c (org-persist-write:generic c collection)))
(plist-get collection :container)))) (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)))))))) (or ignore-return (org-persist-read container associated))))))))
(defun org-persist-write-all (&optional associated) (defun org-persist-write-all (&optional associated)