Hi,
I noticed (and apparently someone else on comp.lang.lisp, too)
that concatenate could be a lot faster, at least for simple-array
types.
Personally, I use concatenate mostly with two or three
simple-string arguments and with 'string as result type.
Grepping through the various CL libraries I have lying
around, it seems that this is really the most common use
case (say >= 3/4).
So I've created specialized concat-simple-string2 and
concate-simple-string3 functions and a compiler macro
for concatenate that converts certain calls to
concatenate to concatenate-simple-string2 or
concatenate-simple-string3. I've checked and Allegro also
has a compiler macro for concatenate.
It gives me a speedup of about an order of magnitude.
The patch should be attached. Sbcl builds and tests pass
with it. Would be nice if this or something similar in
effect would make it into CVS.
Some (time ...) before/after comparisons:
CL-USER> (defparameter *s1* (make-string 100 :initial-element #\a))
*S1*
CL-USER> (defparameter *s2* (make-string 100 :initial-element #\b))
*S2*
CL-USER> (defparameter *s3* (make-string 100 :initial-element #\c))
*S3*
CL-USER> (defparameter *v* nil)
*V*
;;; Before
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string "a" "b"))))
Evaluation took:
2.187 seconds of real time
2.160135 seconds of user run time
0.008001 seconds of system run time
[Run times include 0.124 seconds GC run time.]
0 calls to %EVAL
0 page faults and
111,998,504 bytes consed.
NIL
;;; After
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string "a" "b"))))
Evaluation took:
0.143 seconds of real time
0.144009 seconds of user run time
0.0 seconds of system run time
[Run times include 0.02 seconds GC run time.]
0 calls to %EVAL
0 page faults and
24,004,280 bytes consed.
NIL
;;; Before
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string "a" "b" "c"))))
Evaluation took:
2.438 seconds of real time
2.372148 seconds of user run time
0.008 seconds of system run time
[Run times include 0.092 seconds GC run time.]
0 calls to %EVAL
0 page faults and
152,000,736 bytes consed.
NIL
;;; After
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string "a" "b" "c"))))
Evaluation took:
0.2 seconds of real time
0.196013 seconds of user run time
0.0 seconds of system run time
[Run times include 0.032 seconds GC run time.]
0 calls to %EVAL
0 page faults and
24,004,824 bytes consed.
NIL
;;; Before
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string *s1* *s2*))))
Evaluation took:
25.206 seconds of real time
24.94156 seconds of user run time
0.024002 seconds of system run time
[Run times include 0.452 seconds GC run time.]
0 calls to %EVAL
0 page faults and
903,957,528 bytes consed.
NIL
;;; After
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string *s1* *s2*))))
Evaluation took:
2.044 seconds of real time
2.028127 seconds of user run time
0.016001 seconds of system run time
[Run times include 0.5 seconds GC run time.]
0 calls to %EVAL
0 page faults and
815,950,896 bytes consed.
NIL
;;; Before
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string *s1* *s2* *s3*))))
Evaluation took:
37.812 seconds of real time
36.366272 seconds of user run time
0.056004 seconds of system run time
[Run times include 0.72 seconds GC run time.]
0 calls to %EVAL
0 page faults and
1,343,888,536 bytes consed.
NIL
;;; After
CL-USER> (time (loop repeat 1000000
do (setf *v* (concatenate 'string *s1* *s2* *s3*))))
Evaluation took:
3.44 seconds of real time
3.404213 seconds of user run time
0.020001 seconds of system run time
[Run times include 0.744 seconds GC run time.]
0 calls to %EVAL
0 page faults and
1,215,885,088 bytes consed.
NIL
Stefan
|