From b6c5515efa8b50f113b2835ffcb87d878b55444d Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Tue, 19 May 2020 09:08:05 -0600 Subject: [PATCH] cs: faster `write-char` on ASCII --- racket/src/io/port/bytes-output.rkt | 35 ++++++++++++++------------- racket/src/io/port/string-output.rkt | 36 ++++++++++++++++------------ 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/racket/src/io/port/bytes-output.rkt b/racket/src/io/port/bytes-output.rkt index 0924093821..77765e1434 100644 --- a/racket/src/io/port/bytes-output.rkt +++ b/racket/src/io/port/bytes-output.rkt @@ -21,25 +21,28 @@ unsafe-write-bytes) (module+ internal - (provide do-write-bytes)) + (provide do-write-byte + do-write-bytes)) (define/who (write-byte b [out (current-output-port)]) (check who byte? b) - (check who output-port? out) - (let ([out (->core-output-port out)]) - (start-atomic) - (define buffer (core-port-buffer out)) - (define pos (direct-pos buffer)) - (cond - [(pos . fx< . (direct-end buffer)) - (bytes-set! (direct-bstr buffer) pos b) - (set-direct-pos! buffer (fx+ pos 1)) - (when (core-port-count out) - (port-count-byte! out b)) - (end-atomic)] - [else - (end-atomic) - (write-some-bytes 'write-byte out (bytes b) 0 1 #:buffer-ok? #t #:copy-bstr? #f)])) + (do-write-byte b (->core-output-port out who))) + +;; `out` must be a core output port +(define (do-write-byte b out) + (start-atomic) + (define buffer (core-port-buffer out)) + (define pos (direct-pos buffer)) + (cond + [(pos . fx< . (direct-end buffer)) + (bytes-set! (direct-bstr buffer) pos b) + (set-direct-pos! buffer (fx+ pos 1)) + (when (core-port-count out) + (port-count-byte! out b)) + (end-atomic)] + [else + (end-atomic) + (write-some-bytes 'write-byte out (bytes b) 0 1 #:buffer-ok? #t #:copy-bstr? #f)]) (void)) (define (do-write-bytes who out bstr start end) diff --git a/racket/src/io/port/string-output.rkt b/racket/src/io/port/string-output.rkt index 0e28ad13c7..4c153a8f53 100644 --- a/racket/src/io/port/string-output.rkt +++ b/racket/src/io/port/string-output.rkt @@ -10,23 +10,29 @@ (define/who (write-char ch [out (current-output-port)]) (check who char? ch) - (check who output-port? out) - (write-string (string ch) out 0 1) + (let ([out (->core-output-port out who)]) + (define v (char->integer ch)) + (if (v . < . 128) + (do-write-byte v out) + (do-write-string who (string ch) out 0 1))) (void)) (define/who (write-string str [out (current-output-port)] [start 0] [end (and (string? str) (string-length str))]) (check who string? str) - (check who output-port? out) - (check who exact-nonnegative-integer? start) - (check who exact-nonnegative-integer? end) - (check-range who start end (string-length str) str) - (let ([out (->core-output-port out)]) - (let loop ([i start]) - (cond - [(= i end) (- i start)] - [else - (define next-i (min end (+ i 4096))) - (define bstr (string->bytes/utf-8 str 0 i next-i)) - (do-write-bytes who out bstr 0 (bytes-length bstr)) - (loop next-i)])))) + (let ([out (->core-output-port out who)]) + (check who exact-nonnegative-integer? start) + (check who exact-nonnegative-integer? end) + (check-range who start end (string-length str) str) + (do-write-string who str out start end))) + +;; `out` must be a core output port +(define (do-write-string who str out start end) + (let loop ([i start]) + (cond + [(= i end) (- i start)] + [else + (define next-i (min end (+ i 4096))) + (define bstr (string->bytes/utf-8 str 0 i next-i)) + (do-write-bytes who out bstr 0 (bytes-length bstr)) + (loop next-i)])))