Sorry for replying to my own message, but ...
I've suggested before to Marc that he inline at least the fast path to read-char, so that would be about (from _io.scm):
(define-prim (##read-char port)
(##declare (not interrupts-enabled))
(macro-port-mutex-lock! port) ; get exclusive access to port
(let loop ()
(let ((char-rlo (macro-character-port-rlo port)) (char-rhi (macro-character-port-rhi port))) (if (##fixnum.< char-rlo char-rhi)
; the next character is in the character read buffer
(let ((c (##string-ref (macro-character-port-rbuf port) char- rlo))) (if (##not (##char=? c #\newline))
; frequent simple case, just advance rlo
(begin (macro-character-port-rlo-set! port (##fixnum.+ char- rlo 1)) (macro-port-mutex-unlock! port) c) ....
plus some checking code that port is a character-input-port:
(define-prim (read-char #!optional (port (macro-absent-obj))) (macro-force-vars (port) (let ((p (if (##eq? port (macro-absent-obj)) (macro-current-input-port) port))) (macro-check-character-input-port p 1 (read-char p) (##read-char p)))))
Maybe that's still a good idea. The corresponding code in the standard C library is a macro that expands to something like this.
Brad