From: Stefan k. Bamberger
Subject: re: list to string etc.
Date: 
Message-ID: <bambi-1012961603220001@wi6a84.informatik.uni-wuerzburg.de>
I cut several lines to save space. I hope I didn't change the semantic.


First of all: I agree with Thomas that one always should use the function
which is just sufficient for one's task. My additional statement is, that
it's not so easy to find it... . A function which is very efficient in a
specific implementation is not worth it in another. And a function (like
format) which looks very complex and time intensive could be very helpful
in certain circumstances.
Especiallly if you write code to run on several (hardware) platforms you
always have to find again and again the different software/implementation
bottlenecks and treat them individually.
It would be a nice addendum to ANSI CL to nail down which function should
be provided more efficient than others to get a better feeling how to
write platform independent FAST code.

In the meanwhile I got a mail from Nat Makarevitch (I didn't see it as a
news so I give a summary here) whichs shows that princ-to-string in CLISP
is faster than format (x3) (tested on LINUX). But even there
PRINC-TO-STRING needs more space.



In article <··········@nz12.rz.uni-karlsruhe.de>, ···@ira.uka.de (Thomas
Kaeufl) wrote:

[.. lines cut...]

> Then, I did his benchmarks in Lucid Common Lisp and got these results
> 
> (time
>  (dotimes (var 1000)
>    (apply #'concatenate 'string
>           (mapcar #'princ-to-string '(a b c d)))))
> 
...
> Total Run Time    = 0.75 seconds
...
> Ephemeral Bytes Consed =    148,952
> 
> (time
>  (dotimes (var 1000)
>    (format nil "~{~a~}" '(a b c d))))
> 
...
> Total Run Time    = 0.88 seconds
...
> Ephemeral Bytes Consed =     60,752
> 

It looks for me that format is still more (memory) efficient with roughly
the same run time.


> 
> Then, I tested a typical use of PRINC-TO-STRING in the software developed
> at our institute and got these results. (The number comes from a counter.)
> 
> (time
>  (dotimes (var 1000)
>    (concatenate 'string (princ-to-string 'ab) (princ-to-string '!)
>                 (princ-to-string 1))))
> 
...
> Total Run Time    = 0.61 seconds
...
> Ephemeral Bytes Consed =     93,224
> 
> (time
>  (dotimes (var 1000)
>    (format  nil "~{~S~}" (list (princ-to-string 'ab) (princ-to-string '!)
>                                (princ-to-string 1)))))
> 
...
> Total Run Time    = 1.19 seconds
...
> Ephemeral Bytes Consed =    109,416
> 
> So, in Lucid PRINC-TO-STRING seems to work more efficient.
> 
......

Are you sure you compare the same things? In the second example you create
an extra list which you decompose in the format again. Perhaps I miss the
point what you want to demonstrate.

I would write:

(time
  (dotimes (var 1000)
    (format  nil "~a~a~a" 'ab '! 1)))

In my MCL 4.0 version on a power mac.

(Dotimes (Var 1000) (Format Nil "~a~a~a" 'Ab '! 1)) took 382 milliseconds
(0.382 seconds) to run.
 8,000 bytes of memory allocated.

against

(Dotimes (Var 1000) (Concatenate 'String (Princ-To-String 'Ab)
(Princ-To-String '!) (Princ-To-String 1))) took 877 milliseconds (0.877
seconds) to run.
 200,000 bytes of memory allocated.


- stefan
From: Thomas Kaeufl
Subject: Re: list to string etc.
Date: 
Message-ID: <58p63u$epj@nz12.rz.uni-karlsruhe.de>
·····@informatik.uni-wuerzburg.de (Stefan k. Bamberger) wrote:

> In the second example you create
> an extra list which you decompose in the format again. Perhaps I miss the
> point what you want to demonstrate.

> I would write:

> (time
>   (dotimes (var 1000)
>     (format  nil "~a~a~a" 'ab '! 1)))

Stefan is right. I should have written this call of format too.

After my posting in this group I got a mail from Howard R. Stearns. He writes

> If you want to measure performance of compiled code, than you need to
> compile the code.

So, following his advice I compiled the following functions

(DEFUN GENERATE.CONSTANT (VAR)
  (DECLARE (TYPE (OR SYMBOL ······@TERM) VAR))
  (CONCATENATE 'STRING (PRINC-TO-STRING VAR) "!"
	       (PRINC-TO-STRING
		 (THE FIXNUM (FUNCALL TEQ=CONSTANT.GENERATOR.COUNTER)))))

(This is our typical application I mentioned. TEQ=CONSTANT.GENERATOR.COUNTER
is a counter.)

(DEFUN MEASURE.PRINC ()
  (TIME (DOTIMES (VAR 1000) (GENERATE.CONSTANT 'X))))


(DEFUN GENERATE.CONSTANT.F (VAR)
  (DECLARE (TYPE (OR SYMBOL ······@TERM) VAR))
  (FORMAT NIL "~A~A~A" VAR "!"
	  (THE FIXNUM (FUNCALL TEQ=CONSTANT.GENERATOR.COUNTER))))

(defun measure.format ()
  (time (dotimes (var 1000) (GENERATE.CONSTANT.F 'X))))

and obtained the following results:

(MEASURE.PRINC)
Elapsed Real Time = 0.60 seconds
Total Run Time    = 0.56 seconds
User Run Time     = 0.55 seconds
System Run Time   = 0.01 seconds
Process Page Faults    =        128
Dynamic Bytes Consed   =          0
Ephemeral Bytes Consed =    136,016
NIL

(MEASURE.FORMAT)
Elapsed Real Time = 0.89 seconds
Total Run Time    = 0.88 seconds
User Run Time     = 0.88 seconds
System Run Time   = 0.00 seconds
Process Page Faults    =         11
Dynamic Bytes Consed   =          0
Ephemeral Bytes Consed =     64,088
NIL


Thomas Kaeufl
······@ira.uka.de