Skip to content

Commit 063428f

Browse files
committed
Rewrite nrepl-log--pp-listlike as a single pass
The old implementation copy-sequence'd the cdr, seq-partition'd into pairs, sorted alphabetically, seq-map'd for name lengths, seq-max'd, seq-filter + seq-remove'd to split off special keys, seq-concatenate'd twice, apply'd seq-concatenate to flatten back into a plist, then cl-loop'd to emit -- roughly six list-sized allocations plus an O(n log n) sort per logged message, half of it just to assemble a plist that immediately got destructured again. Replace with one pass: bucket special keys into a fixed-position vector (so they emit in canonical id/op/session/time-stamp order without sorting), collect the rest in insertion order, and track the widest key inline for column alignment. No more sort, no more copy-sequence, allocations down to a single small vector plus the others list. Behavior change: non-special keys now print in the order they appeared in the dict instead of alphabetically. The order reflects how the peer constructed the message, which is more useful for protocol debugging than alphabetic by accident.
1 parent 7999c4e commit 063428f

1 file changed

Lines changed: 27 additions & 20 deletions

File tree

lisp/nrepl-client.el

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,6 +1396,9 @@ If ID is nil, return nil."
13961396
(mod (length nrepl-message-colors))
13971397
(nth nrepl-message-colors))))
13981398

1399+
(defconst nrepl-log--special-keys '("id" "op" "session" "time-stamp")
1400+
"Keys that are displayed first, in this order, in `nrepl-log--pp-listlike'.")
1401+
13991402
(defun nrepl-log--pp-listlike (object &optional foreground button)
14001403
"Pretty print nREPL list like OBJECT.
14011404
FOREGROUND and BUTTON are as in `nrepl-log-pp-object'."
@@ -1407,28 +1410,32 @@ FOREGROUND and BUTTON are as in `nrepl-log-pp-object'."
14071410
(insert (color head))
14081411
(if (null (cdr object))
14091412
(insert ")\n")
1413+
;; Walk the plist once: bucket pairs whose key is in
1414+
;; `nrepl-log--special-keys' into a fixed-position vector so they
1415+
;; emit in canonical order, collect the rest in insertion order,
1416+
;; and track the widest key for column alignment. Replaces a
1417+
;; pipeline that copy-sequence'd, partitioned, sorted, mapped,
1418+
;; filtered, removed, and concatenated the plist for every message.
14101419
(let* ((indent (+ 2 (- (current-column) (length head))))
1411-
(sorted-pairs (sort (seq-partition (copy-sequence (cdr object)) 2)
1412-
(lambda (a b)
1413-
(string< (car a) (car b)))))
1414-
(name-lengths (seq-map (lambda (pair) (length (car pair))) sorted-pairs))
1415-
(longest-name (seq-max name-lengths))
1416-
;; Special entries are displayed first
1417-
(specialq (lambda (pair) (member (car pair) '("id" "op" "session" "time-stamp"))))
1418-
(special-pairs (seq-filter specialq sorted-pairs))
1419-
(not-special-pairs (seq-remove specialq sorted-pairs))
1420-
(all-pairs (seq-concatenate 'list special-pairs not-special-pairs))
1421-
(sorted-object (apply #'seq-concatenate 'list all-pairs)))
1420+
(specials (make-vector (length nrepl-log--special-keys) nil))
1421+
(others nil)
1422+
(longest-name 0))
1423+
(cl-loop for (k v) on (cdr object) by #'cddr
1424+
do (setq longest-name (max longest-name (length k)))
1425+
do (let ((idx (cl-position k nrepl-log--special-keys :test #'equal)))
1426+
(if idx
1427+
(aset specials idx (cons k v))
1428+
(push (cons k v) others))))
14221429
(insert "\n")
1423-
(cl-loop for l on sorted-object by #'cddr
1424-
do (let ((indent-str (make-string indent ?\s))
1425-
(name-str (propertize (car l) 'face
1426-
;; Only highlight top-level keys.
1427-
(unless (eq (car object) 'dict)
1428-
'font-lock-keyword-face)))
1429-
(spaces-str (make-string (- longest-name (length (car l))) ?\s)))
1430-
(insert (format "%s%s%s " indent-str name-str spaces-str))
1431-
(nrepl-log-pp-object (cadr l) nil button)))
1430+
(let ((indent-str (make-string indent ?\s))
1431+
;; Only highlight top-level keys.
1432+
(face (unless (eq (car object) 'dict) 'font-lock-keyword-face)))
1433+
(dolist (pair (nconc (delq nil (append specials nil)) (nreverse others)))
1434+
(let* ((k (car pair))
1435+
(v (cdr pair))
1436+
(spaces-str (make-string (- longest-name (length k)) ?\s)))
1437+
(insert indent-str (propertize k 'face face) spaces-str " ")
1438+
(nrepl-log-pp-object v nil button))))
14321439
(when (eq (car object) 'dict)
14331440
(delete-char -1))
14341441
(insert (color ")\n")))))))

0 commit comments

Comments
 (0)