perf(pty): reuse a per-fd read buffer

ober

9199121eff63ced6c9e201a4b44440c465faebe4

diff --git a/src/jerboa-emacs/pty.ss b/src/jerboa-emacs/pty.ss
index c262c13..4ac70d6 100644
--- a/src/jerboa-emacs/pty.ss
+++ b/src/jerboa-emacs/pty.ss
@@ -84,10 +84,17 @@
       (values (ffi-pty-get-master-fd) result)
       (values #f #f))))
 
+;; Reusable per-fd read buffer: avoids allocating a fresh 4KB bytevector on
+;; every PTY read. Keyed by master fd so concurrent PTYs don't share a buffer.
+(def *pty-read-buffers* (make-eqv-hashtable))
+
 (def (pty-read master-fd)
   "Read from PTY master fd.
    Returns: string (data), #f (EAGAIN/retry), 'eof (true EOF), or 'error (fatal)."
-  (let* ((buf (make-bytevector 4096 0))
+  (let* ((buf (or (hashtable-ref *pty-read-buffers* master-fd #f)
+                  (let ((b (make-bytevector 4096 0)))
+                    (hashtable-set! *pty-read-buffers* master-fd b)
+                    b)))
          (n (ffi-pty-read master-fd buf 4095)))
     (cond
       ((> n 0)
@@ -109,6 +116,7 @@
 
 (def (pty-close! master-fd child-pid)
   (ffi-pty-close master-fd)
+  (hashtable-delete! *pty-read-buffers* master-fd)
   (when (and child-pid (> child-pid 0))
     (with-catch (lambda (e) (void))
       (lambda ()