From: Alberto Lavelli
Subject: FORMAT vs WRITE
Date: 
Message-ID: <9d8prc$h06$1@fe2.cs.interbusiness.it>
A few days ago in the newsgroup it was mentioned the fact that FORMAT
is rather expensive and WRITE, WRITE-STRING, etc. should be preferred. 

I did a very rough test with two versions of a function, one using
FORMAT and the other using WRITE (the two functions are shown at the
end of the message).  BTW, I'm using ACL 5.0.1. I found out (see the
results shown below) that the total cpu time spent by the WRITE
version is one third bigger than the time spent by the FORMAT version;
but the FORMAT version conses about 60% more than the WRITE version.
If the application uses FORMAT a lot (as mine does) all these conses
produce a lot of garbage that must be later collected and so the WRITE
version is likely to perform better because of smaller gc time.

After this premise, here is my question for the people in the
newsgroup.  Does the same apply to the use of FORMAT to produce
strings?  Is usually more advisable to use WRITE-TO-STRING instead of
FORMAT as well?  My application uses FORMAT both to produce strings
and to output to files so it could benefit from this change. But this
transformation can be quite costly and so I would like to be
relatively sure that it can be effective before starting to modify my
code.

Thanks in advance

	alberto


--------------- TEST RESULTS

USER(26): (time (with-open-file (stream "test-write" 
                                 :direction :output 
                                 :if-exists :supersede 
                                 :if-does-not-exist :create)
		 (dotimes (i 10000) 
                   (test-write stream 10 :TA "A S" 1000 NIL NIL "A S" 3))))
; cpu time (non-gc) 2,090 msec user, 20 msec system
; cpu time (gc)     10 msec user, 0 msec system
; cpu time (total)  2,100 msec user, 20 msec system
; real time  3,805 msec
; space allocation:
;  270,171 cons cells, 2 symbols, 6,024 other bytes, 0 static bytes
NIL
USER(27): (time (with-open-file (stream "test-format" 
                                 :direction :output 
                                 :if-exists :supersede 
                                 :if-does-not-exist :create)
		 (dotimes (i 10000) 
                   (test-format stream 10 :TA "A S" 1000 NIL NIL "A S" 3))))
; cpu time (non-gc) 1,530 msec user, 20 msec system
; cpu time (gc)     40 msec user, 0 msec system
; cpu time (total)  1,570 msec user, 20 msec system
; real time  3,151 msec
; space allocation:
;  430,178 cons cells, 2 symbols, 10,904 other bytes, 0 static bytes
NIL


--------------- TEST FUNCTIONS

(defun test-format (stream u v w x y z p q)
  (format stream 
          "(b-s-r :m ~D :l ~S :ta '~S :o ···@[~%     :o-c ~S ~]·@[:w-c ~S~]~%    :p ~A :d ~D)~%~%"
	  u v w x y z p q))

(defun test-write (stream u v w x y z p q)
  (write-string "(b-s-r :m " stream)
  (write u :stream stream)
  (write-string " :l " stream)
  (write v :stream stream)
  (write-string " :ta '" stream)
  (write w :stream stream)
  (write-string " :o " stream)
  (write x :stream stream)
  (when y
    (write-string " :o-c " stream)
    (write y :stream stream))
  (when z
    (write-string " :o-w " stream)
    (write z :stream stream))
  (terpri stream)
  (write-string "    :p " stream)
  (write-string p stream)
  (write-string " :d " stream)
  (write q :stream stream)
  (write-string ")" stream)
  (terpri stream)
  (terpri stream))

From: Espen Vestre
Subject: Re: FORMAT vs WRITE
Date: 
Message-ID: <w67kzsyn01.fsf@wallace.ws.nextra.no>
·······@irst.it (Alberto Lavelli) writes:

> I did a very rough test with two versions of a function, one using
> FORMAT and the other using WRITE (the two functions are shown at the
> end of the message).  BTW, I'm using ACL 5.0.1. I found out (see the

I think you must have forgotten to compile the two functions, I can't
explain the enormous memory usage in any other way.

Here's what I get in a slightly modified version in lispworks (I also
compiled the test function itself, as you can see):

HC 87 > (defun testwrite (function)
          (time (with-open-file (stream "test-write" 
                                 :direction :output 
                                 :if-exists :supersede 
                                 :if-does-not-exist :create)
		 (dotimes (i 10000) 
                   (funcall function stream 10 :TA "A S" 1000 NIL NIL "A S" 3)))))
TESTWRITE

HC 88 > (compile *)
TESTWRITE
NIL
NIL
HC 93 > (testwrite #'test-format)
Timing the evaluation of (WITH-OPEN-FILE (STREAM "test-write" :DIRECTION :OUTPUT :IF-EXISTS :SUPERSEDE :IF-DOES-NOT-EXIST :CREATE) (DOTIMES (I 10000) (FUNCALL FUNCTION STREAM 10 :TA "A S" 1000 NIL NIL "A S" 3)))

user time    =      1.410
system time  =      0.000
Elapsed time =   0:00:02
Allocation   = 10548 bytes
0 Page faults
NIL

HC 94 > (testwrite #'test-write)
Timing the evaluation of (WITH-OPEN-FILE (STREAM "test-write" :DIRECTION :OUTPUT :IF-EXISTS :SUPERSEDE :IF-DOES-NOT-EXIST :CREATE) (DOTIMES (I 10000) (FUNCALL FUNCTION STREAM 10 :TA "A S" 1000 NIL NIL "A S" 3)))

user time    =      0.880
system time  =      0.010
Elapsed time =   0:00:01
Allocation   = 10256 bytes
0 Page faults
NIL

-- 
  (espen)
From: Tim Bradshaw
Subject: Re: FORMAT vs WRITE
Date: 
Message-ID: <nkjheyvx54f.fsf@tfeb.org>
·······@irst.it (Alberto Lavelli) writes:

> 
> I did a very rough test with two versions of a function, one using
> FORMAT and the other using WRITE (the two functions are shown at the
> end of the message).  BTW, I'm using ACL 5.0.1. I found out (see the
> results shown below) that the total cpu time spent by the WRITE
> version is one third bigger than the time spent by the FORMAT version;
> but the FORMAT version conses about 60% more than the WRITE version.
> If the application uses FORMAT a lot (as mine does) all these conses
> produce a lot of garbage that must be later collected and so the WRITE
> version is likely to perform better because of smaller gc time.
> 

Be careful about what you measure.  If you are worried about memory
allocation costs, then run the thing enough so that the GC runs enough
so that you are actually emasuring the cost you think you are.  For
instance if the extra consing that FORMAT does is ephemeral (becomes
garbage very rapidly), and if the first generation size is large
enough, the GC overhead can be very low indeed.  I think that ACL
comes with a fairly conservative setting for the generation sizes -
increasing them can improve GC performance dramaticvally for some
applications, *if* you have a bunch of real memory.

--tim