Subject: bug#51995: 29.0.50; `string-pixel-width' depends on the current window width

From: Brahimi Saifullah <[email-masked]>
Date: Sat, 20 Nov 2021 18:42:01 -0300

>Since 'window-text-pixel-size' has to deal with arbitrary buffers, it is
>not a good idea to set X-LIMIT or Y-LIMIT to very large values.  The
>doc-string of 'window-text-pixel-size' explicitly warns about X-LIMIT
>that
>
>   Since calculating the width of long lines can take some time, it's
>   always a good idea to make this argument as small as possible; in
>   particular, if the buffer contains long lines that shall be truncated
>   anyway.

I saw the warnings, but I'm unsure of their validity.
Here are some benchmarks that I did.  Each form was run on a fresh emacs -Q.
Apologies in advance if there is something wrong about them:

;;; X-LIMIT nil (window width is the limit)
(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "foo")
      (car (window-text-pixel-size nil (point-min) (point))))))
;; (15.551981 588 8.272839)

(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
      (car (window-text-pixel-size nil (point-min) (point))))))
;; (17.975419000000002 588 8.30243)

;;; X-LIMIT is equal to the width of the string plus 1
(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "foo")
      (car (window-text-pixel-size nil (point-min) (point) 25)))))
;; (15.489861 587 8.267005000000001)

(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
      (car (window-text-pixel-size nil (point-min) (point) 873)))))
;; (17.98802 587 8.421413)

;;; X-LIMIT is unreasonably large
(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "foo")
      (car (window-text-pixel-size nil (point-min) (point) 1000000)))))
;; (15.508047000000001 587 8.281872)

(benchmark-run 100000
  (save-window-excursion
    (with-temp-buffer
      (set-window-buffer nil (current-buffer))
      (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
      (car (window-text-pixel-size nil (point-min) (point) 1000000)))))
;; (18.031506 588 8.440261)

The limit actually seems to be rather irrelevant.
Long strings take expectedly longer, but it doesn't
seem related to how big or how small X-LIMIT is.

The following use a buffer as WINDOW,
as `string-pixel-width' currently does:

(benchmark-run 100000
  (with-temp-buffer
    (insert "foo")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point)))))
;; (5.935459 164 2.328032)

(benchmark-run 100000
  (with-temp-buffer
    (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point)))))
;; (8.362771 168 2.349145)

(benchmark-run 100000
  (with-temp-buffer
    (insert "foo")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point) 25))))
;; (5.922218 164 2.350169)

(benchmark-run 100000
  (with-temp-buffer
    (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point) 873))))
;; (7.989145 164 2.2566439999999997)

(benchmark-run 100000
  (with-temp-buffer
    (insert "foo")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point) 1000000))))
;; (5.933362 168 2.378873)

(benchmark-run 100000
  (with-temp-buffer
    (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore")
    (car (window-text-pixel-size
          (current-buffer) (point-min) (point) 1000000))))
;; (8.006855 167 2.318854)

It's a lot more efficient to use a buffer, but the difference
between the limits themselves continue to be insignificant.

--------------------------------------------------------------------------------

>'string-pixel-width' and the accompanying change of
>'window-text-pixel-size' are broken in many ways, see also
>
>   https://mail.gnu.org/archive/html/emacs-devel/2021-11/msg00339.html
>
>If you see a problem that is not mentioned there, please tell us.

Yes, those seem to be the exact problems I was experiencing.

>I hopefully fixed most of the issues here but cannot send you a patch at
>the moment to test because my local copy is completely out of synch with
>master.  So please bear with me.

Take your time :)