unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: David Ponce via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Eli Zaretskii <eliz@gnu.org>
Cc: 72689@debbugs.gnu.org
Subject: bug#72689: 31.0.50; Proposal to improve string-pixel-width
Date: Mon, 19 Aug 2024 10:49:05 +0200	[thread overview]
Message-ID: <fbde3e7d-a780-41cd-8108-6afa5cba57f7@orange.fr> (raw)
In-Reply-To: <8634n219b1.fsf@gnu.org>

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

On 18/08/2024 11:15 AM, Eli Zaretskii wrote:
[...]> I think you understood the issue, and just creating a new buffer if
> the "normal" one is "taken" should be good enough.  I don't expect
> this situation to be a frequent one, so creating too many buffers
> should not be a danger.

Thanks!  Please, find attached a revised V01 patch that implements
your suggestion.  I finally opted to keep only one function,
because setting a few buffer-local variables on each call has not a
significant impact on performance.


[-- Attachment #2: improve-string-pixel-width-V01.patch --]
[-- Type: text/x-patch, Size: 3914 bytes --]

2024-08-19  David Ponce  <da_vid@orange.fr>

	Tweak the implementation of string-pixel-width to run faster and
	use less memory.  Also cater for the case where more than one
	execution thread calls the function (bug#72689).

	* subr-x.el (string--pixel-width-buffer): New variable.
	(string--pixel-width): Use it.  Create a new working buffer when
	parallel run is detected.  Prefer `remove-text-properties' to
	`propertize' to avoid creating a new string on each call.

diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 058c06bc5f6..b688d179da4 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -336,6 +336,8 @@ named-let
       (cl-labels ((,name ,fargs . ,body)) #',name)
       . ,aargs)))
 
+(defvar string--pixel-width-buffer nil)
+
 ;;;###autoload
 (defun string-pixel-width (string &optional buffer)
   "Return the width of STRING in pixels.
@@ -346,21 +348,45 @@ string-pixel-width
       0
     ;; Keeping a work buffer around is more efficient than creating a
     ;; new temporary buffer.
-    (with-current-buffer (get-buffer-create " *string-pixel-width*")
-      ;; If `display-line-numbers' is enabled in internal buffers
-      ;; (e.g. globally), it breaks width calculation (bug#59311)
-      (setq-local display-line-numbers nil)
-      (delete-region (point-min) (point-max))
-      ;; Disable line-prefix and wrap-prefix, for the same reason.
-      (setq line-prefix nil
-	    wrap-prefix nil)
-      (if buffer
-          (setq-local face-remapping-alist
-                      (with-current-buffer buffer
-                        face-remapping-alist))
-        (kill-local-variable 'face-remapping-alist))
-      (insert (propertize string 'line-prefix nil 'wrap-prefix nil))
-      (car (buffer-text-pixel-size nil nil t)))))
+    (with-current-buffer
+        (or (if (buffer-live-p string--pixel-width-buffer)
+                ;; Check if work buffer is not used by
+                ;; another parallel run (bug#72689).  That
+                ;; is, if `string--pixel-width-buffer' has no
+                ;; buffer-local value, in which case the function
+                ;; `buffer-local-value' returns its global value,
+                ;; equal to the work buffer.  Otherwise, when the
+                ;; work buffer is "busy", the buffer-local value of
+                ;; `string--pixel-width-buffer' is nil.
+                (buffer-local-value 'string--pixel-width-buffer
+                                    string--pixel-width-buffer))
+            ;; Create a new work buffer if current is "busy".
+            (setq string--pixel-width-buffer
+                  (generate-new-buffer " *string-pixel-width*" t)))
+      ;; Mark buffer as "busy".
+      (setq-local string--pixel-width-buffer nil)
+      (unwind-protect
+          (progn
+            ;; If `display-line-numbers' is enabled in internal
+            ;; buffers (e.g. globally), it breaks width calculation
+            ;; (bug#59311).  Disable `line-prefix' and `wrap-prefix',
+            ;; for the same reason.
+            (setq display-line-numbers nil
+                  line-prefix nil wrap-prefix nil)
+            (if buffer
+                (setq-local face-remapping-alist
+                            (with-current-buffer buffer
+                              face-remapping-alist))
+              (kill-local-variable 'face-remapping-alist))
+            (erase-buffer)
+            (insert string)
+            ;; Prefer `remove-text-properties' to `propertize' to avoid
+            ;; creating a new string on each call.
+            (remove-text-properties
+             (point-min) (point-max) '(line-prefix nil wrap-prefix nil))
+            (car (buffer-text-pixel-size nil nil t)))
+        ;; Mark buffer as free to use.
+        (kill-local-variable 'string--pixel-width-buffer)))))
 
 ;;;###autoload
 (defun string-glyph-split (string)

  reply	other threads:[~2024-08-19  8:49 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-17 22:03 bug#72689: 31.0.50; Proposal to improve string-pixel-width David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18  4:40 ` Eli Zaretskii
2024-08-18  6:05   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18  9:15     ` Eli Zaretskii
2024-08-19  8:49       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-08-20 15:12       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-21 13:17         ` Eli Zaretskii
2024-08-21 20:43           ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-22  3:43             ` Eli Zaretskii
2024-08-22  9:48               ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-22 10:59                 ` Eli Zaretskii
2024-08-22 14:56                   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-23  6:20                     ` Juri Linkov
2024-08-23  6:49                       ` Eli Zaretskii
2024-08-23  7:23                         ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-31  8:26                     ` Eli Zaretskii
2024-08-31 10:51                       ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-31 12:00                         ` Eli Zaretskii
2024-08-18  6:12 ` Jim Porter
2024-08-18  7:36   ` David Ponce via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-08-18 16:35     ` Jim Porter
2024-08-18  9:23   ` Eli Zaretskii

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=fbde3e7d-a780-41cd-8108-6afa5cba57f7@orange.fr \
    --to=bug-gnu-emacs@gnu.org \
    --cc=72689@debbugs.gnu.org \
    --cc=da_vid@orange.fr \
    --cc=eliz@gnu.org \
    /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).