[Openmcl-devel] Speed of concatenate vs format

Daniel Dickison danieldickison at gmail.com
Fri May 1 12:44:37 PDT 2009


I've been working with some legacy code that contains many instances  
of --

	(format nil "~a~a" string1 string2)

for concatenating strings.  This code is in some code that is a  
performance bottleneck, and I thought, surely, this would be more  
efficient if rewritten as --

	(concatenate 'string string1 string2)

but this turns out not to be the case.  In fact, using format for  
string concatenation is significantly faster.  So assuming the  
overhead for parsing the format control string is negligible, the  
format version probably becomes two calls to princ wrapped in a with- 
output-to-string.  How come this is so much faster than concatenate?

Now that I've done the profiling, I know which code to use, but I'm  
still really curious why this is the case.  I would appreciate any  
insight.  Below is the results of some quick-and-dirty profiling on  
CCL Version 1.3-r11987M  (DarwinX8664), an iMac Core 2 Duo.

Thanks!

Daniel


CL-USER> (defvar *str* (make-string 2000 :initial-element #\a))
*STR*

CL-USER> (time (dotimes (i 100000)
		 (format nil "~a~a" *str* *str*)))
(DOTIMES (I 100000) (FORMAT NIL "~a~a" *STR* *STR*)) took 5,547,598  
microseconds (5.547598 seconds) to run
                     with 2 available CPU cores.
During that period, 3,288,825 microseconds (3.288825 seconds) were  
spent in user mode
                     770,732 microseconds (0.770732 seconds) were  
spent in system mode
1,076,633 microseconds (1.076633 seconds) was spent in GC.
  1,606,416,016 bytes of memory allocated.
NIL

CL-USER> (time (dotimes (i 100000)
		 (concatenate 'string *str* *str*)))
(DOTIMES (I 100000) (CONCATENATE 'STRING *STR* *STR*)) took 10,373,570  
microseconds (10.373570 seconds) to run
                     with 2 available CPU cores.
During that period, 8,092,791 microseconds (8.092791 seconds) were  
spent in user mode
                     878,887 microseconds (0.878887 seconds) were  
spent in system mode
1,097,819 microseconds (1.097819 seconds) was spent in GC.
  1,601,600,000 bytes of memory allocated.
NIL

CL-USER> (time (dotimes (i 100000)
		 (with-output-to-string (s)
		   (princ *str* s)
		   (princ *str* s))))
(DOTIMES (I 100000) (WITH-OUTPUT-TO-STRING (S) (PRINC *STR* S) (PRINC  
*STR* S))) took 5,284,978 microseconds (5.284978 seconds) to run
                     with 2 available CPU cores.
During that period, 3,153,681 microseconds (3.153681 seconds) were  
spent in user mode
                     752,712 microseconds (0.752712 seconds) were  
spent in system mode
1,087,328 microseconds (1.087328 seconds) was spent in GC.
  1,606,416,016 bytes of memory allocated.




More information about the Openmcl-devel mailing list