aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Pettersson2024-02-28 13:03:56 +0100
committerEli Zaretskii2024-03-12 15:22:24 +0200
commit7c552b22e64fa9173557e3511aa4e37ac1d5ea59 (patch)
tree15584044f6efe3e816fc265752c7ec6b8e2356e7
parentd5773276fb1671da619eeee2c316098d6b1c25c4 (diff)
downloademacs-7c552b22e64fa9173557e3511aa4e37ac1d5ea59.tar.gz
emacs-7c552b22e64fa9173557e3511aa4e37ac1d5ea59.zip
Jsonrpc: improve performance of process filter function
`run-at-time' keeps `timer-list' list sorted by inserting each timer based on the timer value. This means that `timer--time-less-p' needs is executed ~N*N/2 times for each N pending messages. This means that jsonrpc becomes unusable for connections that generate a lot messages at the same time. * lisp/jsonrpc.el (Version): Bump to 1.0.25. (jsonrpc--process-filter): Improve performance by activating timers in a different order. (Bug#69241)
-rw-r--r--lisp/jsonrpc.el28
1 files changed, 19 insertions, 9 deletions
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 14fe0447008..5037d8c5b2b 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -4,7 +4,7 @@
4 4
5;; Author: João Távora <joaotavora@gmail.com> 5;; Author: João Távora <joaotavora@gmail.com>
6;; Keywords: processes, languages, extensions 6;; Keywords: processes, languages, extensions
7;; Version: 1.0.24 7;; Version: 1.0.25
8;; Package-Requires: ((emacs "25.2")) 8;; Package-Requires: ((emacs "25.2"))
9 9
10;; This is a GNU ELPA :core package. Avoid functionality that is not 10;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -760,10 +760,11 @@ With optional CLEANUP, kill any associated buffers."
760 (setq message 760 (setq message
761 (plist-put message :jsonrpc-json 761 (plist-put message :jsonrpc-json
762 (buffer-string))) 762 (buffer-string)))
763 (process-put proc 'jsonrpc-mqueue 763 ;; Put new messages at the front of the queue,
764 (nconc (process-get proc 764 ;; this is correct as the order is reversed
765 'jsonrpc-mqueue) 765 ;; before putting the timers on `timer-list'.
766 (list message))))) 766 (push message
767 (process-get proc 'jsonrpc-mqueue))))
767 (goto-char message-end) 768 (goto-char message-end)
768 (let ((inhibit-read-only t)) 769 (let ((inhibit-read-only t))
769 (delete-region (point-min) (point))) 770 (delete-region (point-min) (point)))
@@ -782,11 +783,20 @@ With optional CLEANUP, kill any associated buffers."
782 ;; non-locally (typically the reply to a request), so do 783 ;; non-locally (typically the reply to a request), so do
783 ;; this all this processing in top-level loops timer. 784 ;; this all this processing in top-level loops timer.
784 (cl-loop 785 (cl-loop
786 ;; `timer-activate' orders timers by time, which is an
787 ;; very expensive operation when jsonrpc-mqueue is large,
788 ;; therefore the time object is reused for each timer
789 ;; created.
790 with time = (current-time)
785 for msg = (pop (process-get proc 'jsonrpc-mqueue)) while msg 791 for msg = (pop (process-get proc 'jsonrpc-mqueue)) while msg
786 do (run-at-time 0 nil 792 do (let ((timer (timer-create)))
787 (lambda (m) (with-temp-buffer 793 (timer-set-time timer time)
788 (jsonrpc-connection-receive conn m))) 794 (timer-set-function timer
789 msg))))))) 795 (lambda (conn msg)
796 (with-temp-buffer
797 (jsonrpc-connection-receive conn msg)))
798 (list conn msg))
799 (timer-activate timer))))))))
790 800
791(defun jsonrpc--remove (conn id &optional deferred-spec) 801(defun jsonrpc--remove (conn id &optional deferred-spec)
792 "Cancel CONN's continuations for ID, including its timer, if it exists. 802 "Cancel CONN's continuations for ID, including its timer, if it exists.