[flexi-streams-cvs] r5 - branches/hans
hhubner at common-lisp.net
hhubner at common-lisp.net
Thu May 1 13:41:06 UTC 2008
Author: hhubner
Date: Thu May 1 09:41:05 2008
New Revision: 5
Added:
branches/hans/test-speed.lisp
Modified:
branches/hans/flexi-streams.asd
branches/hans/input.lisp
branches/hans/stream.lisp
branches/hans/strings.lisp
Log:
Speed up string-to-octets by shortcutting through the streams mechanic.
Modified: branches/hans/flexi-streams.asd
==============================================================================
--- branches/hans/flexi-streams.asd (original)
+++ branches/hans/flexi-streams.asd Thu May 1 09:41:05 2008
@@ -49,8 +49,8 @@
(:file "stream")
#+:lispworks (:file "lw-binary-stream")
(:file "output")
- (:file "input")
- (:file "strings"))
+ (:file "strings")
+ (:file "input"))
:depends-on (:trivial-gray-streams))
(defsystem :flexi-streams-test
Modified: branches/hans/input.lisp
==============================================================================
--- branches/hans/input.lisp (original)
+++ branches/hans/input.lisp Thu May 1 09:41:05 2008
@@ -43,8 +43,8 @@
(octet-stack flexi-stream-octet-stack)
(s flexi-stream-stream))
flexi-input-stream
- (declare (integer position)
- (type (or null integer) bound))
+ (declare (fixnum position)
+ (type (or null fixnum) bound))
(when (and bound
(>= position bound))
(return-from read-byte* nil))
@@ -290,9 +290,6 @@
(defmethod stream-read-char ((,stream-var ,stream-class))
"This method was generated with the DEFINE-CHAR-READER macro."
(declare (optimize speed))
- ;; note that we do nothing for the :LF EOL style because we
- ;; assume that #\Newline is the same as #\Linefeed in all
- ;; Lisps which will use this library
(with-accessors ((last-octet flexi-stream-last-octet)
(last-char-code flexi-stream-last-char-code))
,stream-var
@@ -507,6 +504,9 @@
stream
(when (eql char #\Return)
(case (external-format-eol-style external-format)
+ ;; note that we do nothing for the :LF EOL style because we
+ ;; assume that #\Newline is the same as #\Linefeed in all
+ ;; Lisps which will use this library
(:cr (setq char #\Newline
last-char-code #.(char-code #\Newline)))
;; in the case :CRLF we have to look ahead one character
@@ -627,3 +627,14 @@
finally (unless (eql octet eof-value)
(unread-byte octet flexi-input-stream))
(return octet)))
+
+(defun test-buffer-code-char ()
+ (let* ((vector (make-array 2 :element-type '(unsigned-byte 8) :initial-element (char-code #\F)))
+ (buffer (make-to-string-conversion-buffer :vector vector
+ :position 0
+ :end 2
+ :eol-style :nl))
+ (dummy-stream (make-flexi-stream (make-string-input-stream "") :external-format (make-external-format :ascii))))
+ (dotimes (i 1000000)
+ (null (buffer-read-char buffer dummy-stream))
+ (setf (tscb-position buffer) 0))))
\ No newline at end of file
Modified: branches/hans/stream.lisp
==============================================================================
--- branches/hans/stream.lisp (original)
+++ branches/hans/stream.lisp Thu May 1 09:41:05 2008
@@ -170,6 +170,12 @@
MAKE-INSTANCE to create a new FLEXI-OUTPUT-STREAM but use
MAKE-FLEXI-STREAM instead."))
+(defgeneric flexi-stream-output-size-factor (stream)
+ (:documentation "The factor to determine the size of the output
+buffer when converting strings to octets for this format. The size of
+the buffer allocated will be the number of characters in the string to
+convert multiplied by this factor."))
+
#+:cmu
(defmethod input-stream-p ((stream flexi-output-stream))
"Explicitly states whether this is an input stream."
@@ -197,7 +203,7 @@
look ahead for a CR/LF line ending.")
(position :initform 0
:initarg :position
- :type integer
+ :type fixnum
:accessor flexi-stream-position
:documentation "The position within the stream where each
octet read counts as one.")
@@ -327,6 +333,9 @@
(:documentation "The class for all flexi output streams which use an
8-bit encoding."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-8-bit-output-stream))
+ 1)
+
(defclass flexi-cr-8-bit-output-stream (flexi-cr-mixin flexi-8-bit-output-stream)
()
(:documentation "The class for all flexi output streams which
@@ -357,6 +366,9 @@
(:documentation "Special class for flexi output streams which
use the UTF-32 encoding with little-endian byte ordering."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-utf-32-le-output-stream))
+ 4)
+
(defclass flexi-cr-utf-32-le-output-stream (flexi-cr-mixin flexi-utf-32-le-output-stream)
()
(:documentation "Special class for flexi output streams which
@@ -368,6 +380,9 @@
(:documentation "Special class for flexi output streams which
use the UTF-32 encoding with big-endian byte ordering."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-utf-32-be-output-stream))
+ 4)
+
(defclass flexi-cr-utf-32-be-output-stream (flexi-cr-mixin flexi-utf-32-be-output-stream)
()
(:documentation "Special class for flexi output streams which
@@ -379,6 +394,9 @@
(:documentation "Special class for flexi output streams which
use the UTF-16 encoding with little-endian byte ordering."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-utf-16-le-output-stream))
+ 2)
+
(defclass flexi-cr-utf-16-le-output-stream (flexi-cr-mixin flexi-utf-16-le-output-stream)
()
(:documentation "Special class for flexi output streams which
@@ -390,6 +408,9 @@
(:documentation "Special class for flexi output streams which
use the UTF-16 encoding with big-endian byte ordering."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-utf-16-be-output-stream))
+ 2)
+
(defclass flexi-cr-utf-16-be-output-stream (flexi-cr-mixin flexi-utf-16-be-output-stream)
()
(:documentation "Special class for flexi output streams which
@@ -401,6 +422,9 @@
(:documentation "Special class for flexi output streams which
use the UTF-8 encoding."))
+(defmethod flexi-stream-output-size-factor ((stream flexi-utf-8-output-stream))
+ 1.25)
+
(defclass flexi-cr-utf-8-output-stream (flexi-cr-mixin flexi-utf-8-output-stream)
()
(:documentation "Special class for flexi output streams which
Modified: branches/hans/strings.lisp
==============================================================================
--- branches/hans/strings.lisp (original)
+++ branches/hans/strings.lisp Thu May 1 09:41:05 2008
@@ -29,11 +29,31 @@
(in-package :flexi-streams)
+(defmethod write-byte* (byte (array array))
+ (vector-push-extend byte array))
+
(defun string-to-octets (string &key (external-format (make-external-format :latin1))
- (start 0) end)
+ (start 0) (end (length string)))
"Converts the Lisp string STRING from START to END to an array of
octets corresponding to the external format EXTERNAL-FORMAT."
(declare (optimize speed))
+ (declare (type (array character (*)) string))
+ (declare (fixnum start end))
+ (let* ((dummy-stream (make-flexi-stream (make-broadcast-stream) :external-format external-format))
+ (octets (make-array (truncate (* (float (- end start)) (flexi-stream-output-size-factor dummy-stream)))
+ :adjustable t :fill-pointer 0 :element-type '(unsigned-byte 8))))
+ (loop
+ for i of-type fixnum from start below end
+ do (char-to-octets dummy-stream (aref string i) octets))
+ octets))
+
+(defun string-to-octets* (string &key (external-format (make-external-format :latin1))
+ (start 0) end)
+ "Converts the Lisp string STRING from START to END to an array of
+octets corresponding to the external format EXTERNAL-FORMAT. This
+version of STRING-TO-OCTETS is kept around for performance
+comparisons."
+ (declare (optimize speed))
(with-output-to-sequence (out)
(let ((flexi (make-flexi-stream out :external-format external-format)))
(write-string string flexi :start start :end end))))
@@ -83,6 +103,8 @@
;; This version of OCTETS-TO-STRING is here so that one can do speed
;; comparisons. It should be significantly slower than the version
;; above.
+ (declare (type (simple-array (unsigned-byte 8) *) vector))
+ (declare (type (integer 0 *) start end))
(declare (optimize speed))
(with-input-from-sequence (in vector :start start :end end)
(let ((flexi (make-flexi-stream in :external-format external-format))
Added: branches/hans/test-speed.lisp
==============================================================================
--- (empty file)
+++ branches/hans/test-speed.lisp Thu May 1 09:41:05 2008
@@ -0,0 +1,92 @@
+;;; -*- Mode: LISP; Syntax: COMMON-LISP; Package: FLEXI-STREAMS; Base: 10 -*-
+;;; $Header: /usr/local/cvsrep/flexi-streams/input.lisp,v 1.51 2007/12/29 22:58:43 edi Exp $
+
+;;; Copyright (c) 2005-2007, Dr. Edmund Weitz. All rights reserved.
+
+;;; Redistribution and use in source and binary forms, with or without
+;;; modification, are permitted provided that the following conditions
+;;; are met:
+
+;;; * Redistributions of source code must retain the above copyright
+;;; notice, this list of conditions and the following disclaimer.
+
+;;; * Redistributions in binary form must reproduce the above
+;;; copyright notice, this list of conditions and the following
+;;; disclaimer in the documentation and/or other materials
+;;; provided with the distribution.
+
+;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
+;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(in-package :flexi-streams)
+
+(defmacro without-gcing (&body body)
+ `(#+openmcl ccl::without-gcing
+ #+sbcl sb-sys:without-gcing
+ #-(or openmcl sbcl)
+ progn
+ , at body))
+
+(defun test-speed ()
+ (without-gcing
+ (let* ((character-count 10000)
+ (octets (make-array character-count :element-type '(unsigned-byte 8))))
+ (dotimes (i character-count)
+ (setf (aref octets i) (+ 32 (random 96))))
+ (format t "testing with latin-1 encoding, streams based~%")
+ (time (dotimes (i 10)
+ (null (octets-to-string* octets :external-format (make-external-format :latin-1)))))
+ (format t "testing with utf-8 encoding, streams based~%")
+ (time (dotimes (i 10)
+ (null (octets-to-string* octets :external-format (make-external-format :utf-8)))))
+ (format t "testing with latin-1 encoding, optimized~%")
+ (time (dotimes (i 10)
+ (null (octets-to-string octets :external-format (make-external-format :latin-1)))))
+ (format t "testing with utf-8 encoding, optimized~%")
+ (time (dotimes (i 10)
+ (null (octets-to-string octets :external-format (make-external-format :utf-8))))))))
+
+(defmacro profile (&body body)
+ #+sbcl
+ `(progn
+ (sb-profile:reset)
+ (progn
+ , at body)
+ (sb-profile:report)))
+
+
+(defun profile-speed ()
+ #+sbcl
+ (sb-profile:profile "FLEX")
+ (without-gcing
+ (let* ((character-count 1000)
+ (octets (make-array character-count :element-type '(unsigned-byte 8))))
+ (dotimes (i character-count)
+ (setf (aref octets i) (+ 32 (random 96))))
+ (format t "profiling with latin-1 encoding, streams based~%")
+ (profile (dotimes (i 10)
+ (null (octets-to-string* octets :external-format (make-external-format :latin-1)))))
+ (format t "profiling with utf-8 encoding, streams based~%")
+ (profile (dotimes (i 10)
+ (null (octets-to-string* octets :external-format (make-external-format :utf-8)))))
+ (format t "profiling with latin-1 encoding, optimized~%")
+ (profile (dotimes (i 10)
+ (null (octets-to-string octets :external-format (make-external-format :latin-1)))))
+ (format t "profiling with utf-8 encoding, optimized~%")
+ (profile (dotimes (i 10)
+ (null (octets-to-string octets :external-format (make-external-format :utf-8))))))))
+
+(defun fixnum-or-nil (i)
+ (and (oddp i) #.(char-code #\f)))
+
+(defun fixnum-and-nil (i)
+ (values #.(char-code #\f) (oddp i)))
\ No newline at end of file
More information about the Flexi-streams-cvs
mailing list