소스 검색

org-babel-tangle: Do not overwrite when contents does not change

* lisp/ob-tangle.el (org-babel-tangle): Do not overwrite existing
tangled files if their contents is exactly the same as we are going to
write during tangle process.  This avoids unneeded disk writes and can
speed up tangling significantly when many small files are tangled from
a single .org source.

An example of performance improvement when tangling an .org file into
~200 files:
(benchmark-run 10 (org-babel-tangle))
Before the commit (on SSD): (76.33826743 8 11.551725374)
After the commit:           (43.628606052 4 5.751274237)
Ihor Radchenko 3 년 전
부모
커밋
f6f26d4ce4
1개의 변경된 파일18개의 추가작업 그리고 5개의 파일을 삭제
  1. 18 5
      lisp/ob-tangle.el

+ 18 - 5
lisp/ob-tangle.el

@@ -282,11 +282,24 @@ matching a regular expression."
 		    lspecs)
 		   (when make-dir
 		     (make-directory fnd 'parents))
-                   ;; erase previous file
-                   (when (file-exists-p file-name)
-                     (delete-file file-name))
-		   (write-region nil nil file-name)
-		   (mapc (lambda (mode) (set-file-modes file-name mode)) modes)
+                   (unless
+                       (and (file-exists-p file-name)
+                            (let ((tangle-buf (current-buffer)))
+                              (with-temp-buffer
+                                (insert-file-contents file-name)
+                                (and
+                                 (equal (buffer-size)
+                                        (buffer-size tangle-buf))
+                                 (= 0
+                                    (let (case-fold-search)
+                                      (compare-buffer-substrings
+                                       nil nil nil
+                                       tangle-buf nil nil)))))))
+                     ;; erase previous file
+                     (when (file-exists-p file-name)
+                       (delete-file file-name))
+		     (write-region nil nil file-name)
+		     (mapc (lambda (mode) (set-file-modes file-name mode)) modes))
                    (push file-name path-collector))))))
 	 (if (equal arg '(4))
 	     (org-babel-tangle-single-block 1 t)