From: Juho Snellman Date: Thu, 27 Oct 2005 22:30:26 +0000 (+0000) Subject: 0.9.6.3: X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=0d6f1e4381deafc13b09b45833fcb0cc8c2653ac;p=sbcl.git 0.9.6.3: Faster READ-LINE. * Peek directly into the FAST-READ-CHAR buffer at the start of READ-LINE. If it contains a newline, just copy the data directly from the buffer to the result string instead of doing a character-by-character copy. --- diff --git a/src/code/stream.lisp b/src/code/stream.lisp index a8a1350..b2ea43d 100644 --- a/src/code/stream.lisp +++ b/src/code/stream.lisp @@ -223,33 +223,50 @@ (defun ansi-stream-read-line (stream eof-error-p eof-value recursive-p) (declare (ignore recursive-p)) (prepare-for-fast-read-char stream - (let ((res (make-string 80)) - (len 80) - (index 0)) - (loop - (let ((ch (fast-read-char nil nil))) - (cond (ch - (when (char= ch #\newline) - (done-with-fast-read-char) - (return (values (shrink-vector res index) nil))) - (when (= index len) - (setq len (* len 2)) - (let ((new (make-string len))) - (replace new res) - (setq res new))) - (setf (schar res index) ch) - (incf index)) - ((zerop index) - (done-with-fast-read-char) - (return (values (eof-or-lose stream - eof-error-p - eof-value) - t))) - ;; Since FAST-READ-CHAR already hit the eof char, we - ;; shouldn't do another READ-CHAR. - (t - (done-with-fast-read-char) - (return (values (shrink-vector res index) t))))))))) + ;; Check whether the FAST-READ-CHAR buffer contains a newline. If it + ;; does, we can do things quickly by just copying the line from the + ;; buffer instead of doing repeated calls to FAST-READ-CHAR. + (when %frc-buffer% + (locally + ;; For %FIND-POSITION transform + (declare (optimize (speed 2))) + (let ((pos (position #\Newline %frc-buffer% + :test #'char= + :start %frc-index%))) + (when pos + (let* ((len (- pos %frc-index%)) + (res (make-string len))) + (replace res %frc-buffer% :start2 %frc-index% :end2 pos) + (setf %frc-index% (1+ pos)) + (done-with-fast-read-char) + (return-from ansi-stream-read-line res)))))) + (let ((res (make-string 80)) + (len 80) + (index 0)) + (loop + (let ((ch (fast-read-char nil nil))) + (cond (ch + (when (char= ch #\newline) + (done-with-fast-read-char) + (return (values (shrink-vector res index) nil))) + (when (= index len) + (setq len (* len 2)) + (let ((new (make-string len))) + (replace new res) + (setq res new))) + (setf (schar res index) ch) + (incf index)) + ((zerop index) + (done-with-fast-read-char) + (return (values (eof-or-lose stream + eof-error-p + eof-value) + t))) + ;; Since FAST-READ-CHAR already hit the eof char, we + ;; shouldn't do another READ-CHAR. + (t + (done-with-fast-read-char) + (return (values (shrink-vector res index) t))))))))) (defun read-line (&optional (stream *standard-input*) (eof-error-p t) eof-value recursive-p) diff --git a/src/code/sysmacs.lisp b/src/code/sysmacs.lisp index bcb8255..a7e98dd 100644 --- a/src/code/sysmacs.lisp +++ b/src/code/sysmacs.lisp @@ -119,6 +119,9 @@ waits until gc is enabled in this thread." ;;; This macro sets up some local vars for use by the ;;; FAST-READ-CHAR macro within the enclosed lexical scope. The stream ;;; is assumed to be a ANSI-STREAM. +;;; +;;; KLUDGE: Some functions (e.g. ANSI-STREAM-READ-LINE) use these variables +;;; directly, instead of indirecting through FAST-READ-CHAR. (defmacro prepare-for-fast-read-char (stream &body forms) `(let* ((%frc-stream% ,stream) (%frc-method% (ansi-stream-in %frc-stream%)) @@ -134,7 +137,7 @@ waits until gc is enabled in this thread." `(setf (ansi-stream-in-index %frc-stream%) %frc-index%)) ;;; a macro with the same calling convention as READ-CHAR, to be used -;;; within the scope of a PREPARE-FOR-FAST-READ-CHAR +;;; within the scope of a PREPARE-FOR-FAST-READ-CHAR. (defmacro fast-read-char (&optional (eof-error-p t) (eof-value ())) `(cond ((not %frc-buffer%) diff --git a/version.lisp-expr b/version.lisp-expr index 364ce11..98bb3bd 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.9.6.2" +"0.9.6.3"