aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2025-09-04 11:22:57 +0200
committerMattias EngdegÄrd2025-09-07 14:39:24 +0200
commit36c8ebe78a048db7886f070168858d457b486caf (patch)
treefa4bc9f4a368b4e61915fa76c974567ceb02d9c2
parent11b3af64251a899c697b685cf7b311274be8dc6d (diff)
downloademacs-36c8ebe78a048db7886f070168858d457b486caf.tar.gz
emacs-36c8ebe78a048db7886f070168858d457b486caf.zip
Avoid unnecessary text decoding in jsonrpc for speed (bug#79361)
The built-in JSON parser works on undecoded (unibyte) input; decoding received data is just a waste and does take time even when all-ASCII. * lisp/jsonrpc.el (initialize-instance): Use unibyte process buffer and binary coding for process I/O, implying unibyte strings being passed to the filter function. (jsonrpc-connection-send): More efficient message generation. (jsonrpc--json-read): Compatibility code for the old elisp json parser. (jsonrpc--process-filter): Faster header-matching regexp.
-rw-r--r--lisp/jsonrpc.el34
1 files changed, 21 insertions, 13 deletions
diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el
index 6c969120926..bb75196cdc8 100644
--- a/lisp/jsonrpc.el
+++ b/lisp/jsonrpc.el
@@ -548,7 +548,9 @@ connection object, called when the process dies.")
548 (set-process-buffer proc (get-buffer-create (format " *%s output*" name))) 548 (set-process-buffer proc (get-buffer-create (format " *%s output*" name)))
549 (set-process-filter proc #'jsonrpc--process-filter) 549 (set-process-filter proc #'jsonrpc--process-filter)
550 (set-process-sentinel proc #'jsonrpc--process-sentinel) 550 (set-process-sentinel proc #'jsonrpc--process-sentinel)
551 (set-process-coding-system proc 'binary 'binary)
551 (with-current-buffer (process-buffer proc) 552 (with-current-buffer (process-buffer proc)
553 (set-buffer-multibyte nil)
552 (buffer-disable-undo) 554 (buffer-disable-undo)
553 (set-marker (process-mark proc) (point-min)) 555 (set-marker (process-mark proc) (point-min))
554 (let ((inhibit-read-only t)) 556 (let ((inhibit-read-only t))
@@ -578,16 +580,11 @@ connection object, called when the process dies.")
578 (id 'request) 580 (id 'request)
579 (method 'notification))) 581 (method 'notification)))
580 (converted (jsonrpc-convert-to-endpoint connection args kind)) 582 (converted (jsonrpc-convert-to-endpoint connection args kind))
581 (json (jsonrpc--json-encode converted)) 583 (json (jsonrpc--json-encode converted)))
582 (headers
583 `(("Content-Length" . ,(format "%d" (string-bytes json)))
584 ;; ("Content-Type" . "application/vscode-jsonrpc; charset=utf-8")
585 )))
586 (process-send-string 584 (process-send-string
587 (jsonrpc--process connection) 585 (jsonrpc--process connection)
588 (cl-loop for (header . value) in headers 586 (concat "Content-Length: " (number-to-string (string-bytes json)) "\r\n"
589 concat (concat header ": " value "\r\n") into header-section 587 "\r\n" json))
590 finally return (format "%s\r\n%s" header-section json)))
591 (jsonrpc--event 588 (jsonrpc--event
592 connection 589 connection
593 'client 590 'client
@@ -641,11 +638,19 @@ and delete the network process."
641 :false-object :json-false)) 638 :false-object :json-false))
642 (require 'json) 639 (require 'json)
643 (defvar json-object-type) 640 (defvar json-object-type)
644 (declare-function json-read "json" ()) 641 (declare-function json-read-from-string "json" (string))
645 (lambda () 642 (lambda ()
646 (let ((json-object-type 'plist)) 643 (let ((json-object-type 'plist))
647 (json-read)))) 644 ;; `json-read' can't be used because the old json API requires
648 "Read JSON object in buffer, move point to end of buffer.") 645 ;; decoded input.
646 (prog1
647 (json-read-from-string
648 (decode-coding-string
649 (buffer-substring-no-properties (point) (point-max))
650 'utf-8-unix t))
651 (goto-char (point-max))))))
652 "Read JSON object in (binary unibyte) buffer from point.
653Move point to end of buffer.")
649 654
650(defalias 'jsonrpc--json-encode 655(defalias 'jsonrpc--json-encode
651 (if (fboundp 'json-serialize) 656 (if (fboundp 'json-serialize)
@@ -745,8 +750,11 @@ and delete the network process."
745 ;; 750 ;;
746 (setq expected-bytes 751 (setq expected-bytes
747 (and (search-forward-regexp 752 (and (search-forward-regexp
748 "\\(?:.*: .*\r\n\\)*Content-Length: \ 753 (rx bol "Content-Length: " (group (+ digit))
749*\\([[:digit:]]+\\)\r\n\\(?:.*: .*\r\n\\)*\r\n" 754 "\r\n"
755 (* (* (not (in ":\n"))) ": "
756 (* (not (in "\r\n"))) "\r\n")
757 "\r\n")
750 (+ (point) 100) 758 (+ (point) 100)
751 t) 759 t)
752 (string-to-number (match-string 1)))) 760 (string-to-number (match-string 1))))