emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [patch suggestion] Mitigating the poor Emacs performance on huge org files: Do not use overlays for PROPERTY and LOGBOOK drawers
@ 2020-04-24  6:55 Ihor Radchenko
  2020-04-24  8:02 ` Nicolas Goaziou
  0 siblings, 1 reply; 192+ messages in thread
From: Ihor Radchenko @ 2020-04-24  6:55 UTC (permalink / raw)
  To: emacs-orgmode

Emacs becomes very slow when opening and moving around huge org files
with many drawers. I have reported this issue last year in bug-gnu-emacs
[1] and there have been other reports on the same problem in the
internet [2]. You can easily see this problem using the attached file if
you try to move down the lines when all the headings are folded. Moving
a single line down may take over 10 seconds in the file.

According to the reply to my initial emacs bug report [1], the reasons
of performance degradation is huge number of overlays created by org in
the PROPERTY and LOGBOOK drawers. Emacs must loop over all those
overlays every time it calculates where the next visible line is
located. So, one way to improve the performance would be reducing the
number of overlays.

I have been looking into usage of overlays in the org-mode code recently
and tried to redefine org-flag-region to use text properties instead of
overlays:

#+begin_src emacs-lisp
(defun org-flag-region (from to flag spec)
  "Hide or show lines from FROM to TO, according to FLAG.
SPEC is the invisibility spec, as a symbol."
  (pcase spec
    ;; outlines must still use overlays because they rely on
    ;; 'reveal-toggle-invisible feature from reveal.el
    ;; That only works for overlays
    ('outline 
     (remove-overlays from to 'invisible spec)
     ;; Use `front-advance' since text right before to the beginning of
     ;; the overlay belongs to the visible line than to the contents.
     (when flag
       (let ((o (make-overlay from to nil 'front-advance)))
	 (overlay-put o 'evaporate t)
	 (overlay-put o 'invisible spec)
	 (overlay-put o 'isearch-open-invisible #'delete-overlay))))
    (_
     (let ((inhibit-modification-hooks t))
       (remove-text-properties from to '(invisible nil))
       ;; Use `front-advance' since text right before to the beginning of
       ;; the overlay belongs to the visible line than to the contents.
       (when flag
	 (put-text-property from to 'rear-non-sticky t)
	 (put-text-property from to 'front-sticky t)
	 (put-text-property from to 'invisible spec)
         ;; no idea if 'isearch-open-invisible is needed for text
         ;; properties 
	 ;; (overlay-put o 'isearch-open-invisible #'delete-overlay)
	 )))))
#+end_src

To my surprise, the patch did not break org to unusable state and
the performance on the sample org file [3] improved drastically. You can
try by yourself!

However, this did introduce some visual glitches with drawer display.
Though drawers can still be folded/unfolded with <tab>, they are not
folded on org-mode startup for some reason (can be fixed by running
(org-cycle-hide-drawers 'all)). Also, some drawers (or parts of drawers)
are unfolded for no apparent reason sometimes. A blind guess is that it
is something to do with lack of 'isearch-open-invisible, which I am not
sure how to set via text properties.

Any thoughts about the use of text properties or about the patch
suggestion are welcome.  

Best,
Ihor

[1] https://lists.gnu.org/archive/html/bug-gnu-emacs/2019-04/msg01387.html
[2] https://www.reddit.com/r/orgmode/comments/e9p84n/scaling_org_better_to_use_more_medsize_files_or/
[3] See the attached org file in my Emacs bug report: https://lists.gnu.org/archive/html/bug-gnu-emacs/2019-04/txte6kQp35VOm.txt

-- 
Ihor Radchenko,
PhD,
Center for Advancing Materials Performance from the Nanoscale (CAMP-nano)
State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China
Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg



^ permalink raw reply	[flat|nested] 192+ messages in thread