diff options
| author | Daniel Pettersson | 2024-02-28 13:03:56 +0100 |
|---|---|---|
| committer | Eli Zaretskii | 2024-03-12 15:22:24 +0200 |
| commit | 7c552b22e64fa9173557e3511aa4e37ac1d5ea59 (patch) | |
| tree | 15584044f6efe3e816fc265752c7ec6b8e2356e7 | |
| parent | d5773276fb1671da619eeee2c316098d6b1c25c4 (diff) | |
| download | emacs-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.el | 28 |
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. |