unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Stefan Kangas <stefankangas@gmail.com>
To: 75342@debbugs.gnu.org
Cc: Juri Linkov <juri@linkov.net>
Subject: bug#75342: [PATCH] Speed up asynchronous man page fontifying
Date: Sat, 4 Jan 2025 01:22:03 -0600	[thread overview]
Message-ID: <CADwFkmkzr46ALhQv--D+EFadKpBKYjG-fri3MP51NsfdbsyYBg@mail.gmail.com> (raw)

[-- 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


             reply	other threads:[~2025-01-04  7:22 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-04  7:22 Stefan Kangas [this message]
2025-01-04  8:12 ` bug#75342: [PATCH] Speed up asynchronous man page fontifying 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CADwFkmkzr46ALhQv--D+EFadKpBKYjG-fri3MP51NsfdbsyYBg@mail.gmail.com \
    --to=stefankangas@gmail.com \
    --cc=75342@debbugs.gnu.org \
    --cc=juri@linkov.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).