Rudolf Adamkovič <[email protected]> writes:

> [You forgot to CC the list; fixed here.]

Thank you!

> It is objectively simpler than the proposed variant.  Me, I would also
> indent `string-width` below `nth` for maximum readability, and perhaps
> even spell our `index`, making it as 101 as possible:

Sure, good ideas, everything to increase readability!

I tried once more, I am posting here the inline patch with a detailed
description and a benchmark file for further tinkering for anyone
interested.

Best,
-- 
Slawomir Grochowski

>From 500ac779eac1ce1504d299b1f270fa43f066167f Mon Sep 17 00:00:00 2001
From: Slawomir Grochowski <[email protected]>
Date: Wed, 13 May 2026 16:06:22 +0200
Subject: [PATCH] org-colview: Use cl-loop in `org-columns--set-widths'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/org-colview.el (org-columns--set-widths): Rewrite the inner
loop using `cl-loop' with `for ... on ...' iteration over the format
specs and the widths list.

The previous attempt with `while' loop (from f06c61e41) achieved
maximum speed by walking list pointers manually with `cdr', avoiding
the O(k) cost of `nth' on singly-linked lists.  The new variant keeps
the same pointer-walking property - `for ... on ...' exposes the
underlying cons cells, so `(car cons)' / `setcar' remain O(1) — while
adopting the more idiomatic `cl-loop' form.

The O(m) algorithmic improvement from f06c61e41 is preserved: the
cache is still traversed only once.  The earlier `cl-loop' attempt
that was rejected in f06c61e41 relied on `(nth index widths)' which
degraded performance to O(k) per access; the `for ... on ...' form
avoids that pitfall entirely.

Benchmark data (50 runs each, all widths auto-computed from cache):

10 columns (practical case — fits on screen without scrolling):

Rows   Cols  Old O(n×m)   cl-loop nth    cl-loop on     while        Old/nth   Old/on    Old/while
──────────────────────────────────────────────────────────────────────────────────────────────────
10     10    0.00072 s    0.00019 s      0.00015 s      0.00013 s    3.7×      4.9×      5.6×
100    10    0.00183 s    0.00169 s      0.00140 s      0.00098 s    1.1×      1.3×      1.9×
300    10    0.00440 s    0.00502 s      0.00380 s      0.00338 s    0.9×      1.2×      1.3×
500    10    0.00705 s    0.00838 s      0.00633 s      0.00522 s    0.8×      1.1×      1.4×
1000   10    0.01360 s    0.02125 s      0.01569 s      0.01064 s    0.6×      0.9×      1.3×

20 columns (wider, for completeness):

Rows   Cols  Old O(n×m)   cl-loop nth    cl-loop on     while        Old/nth   Old/on    Old/while
──────────────────────────────────────────────────────────────────────────────────────────────────
10     20    0.00084 s    0.00033 s      0.00027 s      0.00045 s    2.5×      3.1×      1.9×
100    20    0.00341 s    0.00340 s      0.00232 s      0.00218 s    1.0×      1.5×      1.6×
300    20    0.00864 s    0.01076 s      0.00804 s      0.00624 s    0.8×      1.1×      1.4×
500    20    0.01434 s    0.01601 s      0.01213 s      0.00998 s    0.9×      1.2×      1.4×
1000   20    0.02912 s    0.03506 s      0.03159 s      0.02042 s    0.8×      0.9×      1.4×

The `cl-loop on' variant trails the `while' by ~10–20% on average,
with measurement noise occasionally inverting the order.  The
trade-off favours readability: the `cl-loop' form expresses the
parallel walk over three lists (triplets, specs, widths) much more
clearly than three interleaved `setq ... (cdr ...)' updates.
---
 lisp/org-colview.el | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/lisp/org-colview.el b/lisp/org-colview.el
index 60ea55a8d..ab1e275f2 100644
--- a/lisp/org-colview.el
+++ b/lisp/org-colview.el
@@ -345,15 +345,14 @@ where:
 				  (`(,_ ,title . ,_) (string-width title))))
 			      org-columns-current-fmt-compiled)))
 	  (dolist (entry cache)
-	    (let ((triplets (cdr entry))
-		  (specs org-columns-current-fmt-compiled)
-		  (w widths))
-	      (while (and triplets specs w)
-		(unless (wholenump (nth 2 (car specs)))
-		  (setcar w (max (car w) (string-width (nth 2 (car triplets))))))
-		(setq triplets (cdr triplets))
-		(setq specs (cdr specs))
-		(setq w (cdr w)))))
+	    (cl-loop for triplet in (cdr entry)
+		     for spec-cons on org-columns-current-fmt-compiled
+		     for width-cons on widths
+		     unless (wholenump (nth 2 (car spec-cons)))
+		     do (setcar width-cons
+				(max (car width-cons)
+				     (string-width
+				      (nth 2 triplet))))))
 	  (apply #'vector widths))))
 
 (defun org-columns--new-overlay (beg end &optional string face)
-- 
2.39.5

Attachment: bench-org-columns-set-widths.el
Description: application/emacs-lisp

Reply via email to