all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#75342: [PATCH] Speed up asynchronous man page fontifying
@ 2025-01-04  7:22 Stefan Kangas
  2025-01-04  8:12 ` Stefan Kangas
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Stefan Kangas @ 2025-01-04  7:22 UTC (permalink / raw)
  To: 75342; +Cc: Juri Linkov

[-- Attachment #1: Type: text/plain, Size: 1552 bytes --]

Severity: wishlist

The below patch makes asynchronous fontifying of man pages faster.

After typing `M-x man RET gcc-14 RET`, it takes around 5 minutes on this
fast MacBook Pro M2 (2022) machine until the whole 1.43 MiB man page is
displayed.  With a hot cache, the best time I have managed to measure is
173.432 seconds.

We seem to call `man--maybe-fontify-manpage` many times on very small
chunks: on my machine, it processes ~30 characters at a time.  Things
get substantially faster if we make `Man-bgproc-filter` fontify the
buffer in much larger chunks.  The main drawback of doing this is that
we risk very briefly seeing an incorrect display flash by in the man
buffer (e.g., with `end-of-buffer`).

My measurements show that 32 KiB might be a good choice, and gives a
~95% speedup:

| Chunk size (KiB) | Completion time (s) |
|------------------+---------------------|
|                4 |                29.3 |
|                8 |                18.2 |
|               16 |                12.7 |
|               32 |                 7.4 |
|               64 |                 6.5 |
|              128 |                 5.4 |

Is this the best approach to optimize something like this, or am I
overlooking something obvious?  Note that I didn't add a variable for
the chunk size, but we could easily add one, if that'd be useful.

When I set `Man-prefer-synchronous-call` to t, it takes ~1.8 seconds to
process the same page.  I guess that this is the lower bound for how
fast we could make the asynchronous call.

Please see the attached.

[-- Attachment #2: 0001-Fontify-man-page-in-32-KiB-chunks.patch --]
[-- Type: text/x-patch, Size: 3053 bytes --]

From 2f677cf4457ae4a2fdf02cee658988da3a27dafc Mon Sep 17 00:00:00 2001
From: Stefan Kangas <stefankangas@gmail.com>
Date: Sat, 4 Jan 2025 07:38:33 +0100
Subject: [PATCH] Fontify man page in 32 KiB chunks

* lisp/man.el (man--bgproc-filter-fontify): New function.
(Man-bgproc-filter): Use above new function; fontify in 32 KiB chunks.
(Man-bgproc-sentinel): Use above new function.
(man--bgproc-filter-last-pos): New variable.
(Man-getpage-in-background): Set above new variable to 0.
---
 lisp/man.el | 32 +++++++++++++++++++++-----------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/lisp/man.el b/lisp/man.el
index 54ca8cbae9f..470d6790ba2 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -417,6 +417,7 @@ Man-reverse
 (defvar-local Man-original-frame nil)
 (defvar-local Man-arguments nil)
 (put 'Man-arguments 'permanent-local t)
+(defvar-local man--bgproc-filter-last-pos nil)
 
 (defvar-local Man--sections nil)
 (defvar-local Man--refpages nil)
@@ -1243,8 +1244,9 @@ Man-getpage-in-background
 			  (Man-shell-file-name)
 			  shell-command-switch
 			  (format (Man-build-man-command) man-args))))
-	       (set-process-sentinel proc 'Man-bgproc-sentinel)
-	       (set-process-filter proc 'Man-bgproc-filter))
+               (set-process-sentinel proc #'Man-bgproc-sentinel)
+               (set-process-filter proc #'Man-bgproc-filter)
+               (setq man--bgproc-filter-last-pos 0))
 	   (let* ((inhibit-read-only t)
 		  (exit-status
 		   (process-file
@@ -1515,6 +1517,19 @@ man--maybe-fontify-manpage
       (Man-fontify-manpage)
     (Man-cleanup-manpage)))
 
+(defun man--bgproc-filter-fontify ()
+  (let ((inhibit-read-only t))
+    (save-restriction
+      (narrow-to-region
+       (save-excursion
+         (goto-char man--bgproc-filter-last-pos)
+         ;; Process whole sections (Bug#36927).
+         (Man-previous-section 1)
+         (point))
+       (point))
+      (setq man--bgproc-filter-last-pos (point))
+      (man--maybe-fontify-manpage))))
+
 (defun Man-bgproc-filter (process string)
   "Manpage background process filter.
 When manpage command is run asynchronously, PROCESS is the process
@@ -1532,15 +1547,9 @@ Man-bgproc-filter
 	    (save-excursion
 	      (goto-char beg)
 	      (insert string)
-	      (save-restriction
-		(narrow-to-region
-		 (save-excursion
-		   (goto-char beg)
-                   ;; Process whole sections (Bug#36927).
-                   (Man-previous-section 1)
-                   (point))
-		 (point))
-		(man--maybe-fontify-manpage))
+              ;; Chunk the processing.
+              (when (>= (- beg man--bgproc-filter-last-pos) 0)
+                (man--bgproc-filter-fontify))
 	      (set-marker (process-mark process) (point-max)))))))))
 
 (defun Man-bgproc-sentinel (process msg)
@@ -1560,6 +1569,7 @@ Man-bgproc-sentinel
 	    (set-process-buffer process nil))
 
       (with-current-buffer Man-buffer
+        (man--bgproc-filter-fontify)
 	(save-excursion
 	  (let ((case-fold-search nil)
                 (inhibit-read-only t))
-- 
2.47.1


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

end of thread, other threads:[~2025-01-05  6:01 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-04  7:22 bug#75342: [PATCH] Speed up asynchronous man page fontifying Stefan Kangas
2025-01-04  8:12 ` Stefan Kangas
2025-01-04  8:27 ` Eli Zaretskii
2025-01-04  9:33   ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
     [not found]   ` <87msg63ov5.fsf@>
2025-01-04 10:03     ` Eli Zaretskii
2025-01-04 21:13       ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors
     [not found]       ` <87frlywae5.fsf@>
2025-01-05  6:01         ` Eli Zaretskii
2025-01-04 21:04 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.