From: Bruno Haible
Subject: Re: format for list printing
Date: 
Message-ID: <5upnvo$lph$1@nz12.rz.uni-karlsruhe.de>
Michael Greenwald <········@Radon.Stanford.EDU> wrote:
>
>>  (let ((i 0)) (dolist (x '(a b c)) (format t "~d. ~a~%" (incf i) x)))
>
> If he's concerned about efficiency then he wouldn't be using FORMAT,
> since the string has to be parsed each call (ignoring format
> compilers, of course).

Really, you should make sure that your Common Lisp implementation supports
the ANSI CL `formatter' macro. Then you write

           (format t (formatter "~d. ~a~%") (incf i) x)

so that the format string is parsed and compiled once and for all.
Decent implementations will even do that for you, by defining `format'
as a compiler-macro which looks at its second argument.

                          Bruno

From: Larry Hunter
Subject: Re: format for list printing
Date: 
Message-ID: <rb2033o13b.fsf@work.nlm.nih.gov>
···········@cctrading.com asks:

   Does this imply that if I am using a "decent implementations" (say,
   CLISP), I should not worry about calling format with the same string 2000
   times (whether the function is compiled or not)?  Or should I define a
   local var and set it to (formatter whatever)?

A quick test in Franz Allegro CL 4.3.1 on a unix box shows that it depends
on the optimization settings.  If you compile with (optimize (speed 1)
(debug 2)) -- the default -- then using a local variable to hold the
formatter closure is about 25% faster.  However, if you compile with
(optimize (speed 3) (debug 0)), then they are effectively identical.

Larry


USER(52): (declaim (optimize (speed 1) (debug 2)))
T
USER(53): (defun test-format1 ()
  (with-open-file (stream "foo" :direction :output :if-exists :supersede)
    (dotimes (i 10000)
      (format stream "~%<~{~a ~}>" '(a b c d e f 1 2 3 4 5 "foo" "bar"
				     "baz" #'(b l a t))))))
TEST-FORMAT1
USER(54): (defun test-format2 ()
  (with-open-file (stream "foo" :direction :output :if-exists :supersede)
    (let ((formatter (formatter "~%<~{~a ~}>" )))
      (dotimes (i 10000)
	(format stream formatter '(a b c d e f 1 2 3 4 5 "foo" "bar"
				   "baz" #'(b l a t)))))))
TEST-FORMAT2
USER(55): (compile 'test-format1)
TEST-FORMAT1
NIL
NIL
USER(56): (compile 'test-format2)
TEST-FORMAT2
NIL
NIL
USER(57): (time (test-format1))
; cpu time (non-gc) 7,600 msec user, 80 msec system
; cpu time (gc)     80 msec user, 0 msec system
; cpu time (total)  7,680 msec user, 80 msec system
; real time  7,979 msec
; space allocation:
;  650,116 cons cells, 0 symbols, 1,845,864 other bytes
NIL
USER(58): (time (test-format2))
; cpu time (non-gc) 5,750 msec user, 70 msec system
; cpu time (gc)     40 msec user, 0 msec system
; cpu time (total)  5,790 msec user, 70 msec system
; real time  6,125 msec
; space allocation:
;  440,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(59): (declaim (optimize (speed 3) (debug 0)))
T
USER(63): (compile 'test-format1)
TEST-FORMAT1
NIL
NIL
USER(66): (compile 'test-format2)
TEST-FORMAT2
NIL
NIL
USER(67): (time (test-format1))
; cpu time (non-gc) 5,710 msec user, 70 msec system
; cpu time (gc)     60 msec user, 0 msec system
; cpu time (total)  5,770 msec user, 70 msec system
; real time  5,995 msec
; space allocation:
;  430,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(68): (time (test-format2))
; cpu time (non-gc) 5,790 msec user, 100 msec system
; cpu time (gc)     50 msec user, 0 msec system
; cpu time (total)  5,840 msec user, 100 msec system
; real time  6,183 msec
; space allocation:
;  440,098 cons cells, 0 symbols, 801,040 other bytes
NIL
USER(69): 
From: Erik Naggum
Subject: Re: format for list printing
Date: 
Message-ID: <3082529264581283@naggum.no>
* Larry Hunter
| A quick test in Franz Allegro CL 4.3.1 on a unix box shows that it
| depends on the optimization settings.  If you compile with (optimize
| (speed 1) (debug 2)) -- the default -- then using a local variable to
| hold the formatter closure is about 25% faster.  However, if you compile
| with (optimize (speed 3) (debug 0)), then they are effectively identical.

optimization in Allegro CL 4.3.1 is controlled by compiler switches.  these
are variables that either hold a value or a function.  if the value is
non-nil or the value of the function is non-nil, the switch is true.

e.g., compilation of format strings is controlled by

    compiler:compile-format-strings-switch

which has a functional value by default.

    user(15): (describe compiler:compile-format-strings-switch)
    #<Function speed > space @ #x165bd2> is a compiled-function.
      The arguments are (safety space speed debug)

we infer that these switch functions receives the values of the various
`optimize' declarations when called by the compiler, so we can write our
own, or we could use a constant value for the appropriate switch.

incidentally, it is sufficient to (declaim (optimize (space 0))) to get
Allegro CL to compile format strings if speed is at least 1.

this is documented in the Allegro CL User Guide, and you should get some
messages when you fire up Allegro CL that indicate how to learn more:

;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the current
;; optimization settings evaluate (explain-compiler-settings).

#\Erik
-- 
404 You're better off without that file.  Trust me.
From: Michael Greenwald
Subject: Re: format for list printing
Date: 
Message-ID: <michaelg.873615097@CS.Stanford.EDU>
······@ma2s2.mathematik.uni-karlsruhe.de (Bruno Haible) writes:

>Michael Greenwald <········@Radon.Stanford.EDU> wrote:
>>
>>>  (let ((i 0)) (dolist (x '(a b c)) (format t "~d. ~a~%" (incf i) x)))
>>
>> If he's concerned about efficiency then he wouldn't be using FORMAT,
>> since the string has to be parsed each call (ignoring format
>> compilers, of course).

>Really, you should make sure that your Common Lisp implementation supports
>the ANSI CL `formatter' macro. 

That's an example of what I meant by "format compilers".