Andreas Klein <klein@cage.ugent.be> wrote:
+---------------
| Hello I found a strange behaviour of cmucl with nested dos.
+---------------
Strange to you, maybe, expected by CMUCL users.
+---------------
| Here is my simple example
|
| (do ((i 1 (+ 1 i)))
| ((= i 1000) nil)
| (do ((j 1 (+ 1 j)))
| ((= j 1000) nil)
| (+ i j)))
|
| And here is what cmucl says
|
| ; [GC threshold exceeded with 12,013,104 bytes in use. Commencing GC.]
| ; [GC completed with 2,267,200 bytes retained and 9,745,904 bytes
| freed.]
+---------------
What, you don't want to see GC messages by default? ;-} ;-}
O.k., just put a (SETF *GC-VERBOSE* NIL) in your
"~/.cmucl-init" file. Personally, I prefer to see
them while developing [and then turn them off in
production, if naive users might see them], but YMMV.
+---------------
| It seams that it wastes a lot of memory.
+---------------
*Conses* a lot, perhaps, but it also recovers *all* of it, too.
On my system, the above runs in less than 4 seconds of elapsed wall
clock time and only GCs 9 times, never using more than ~13.5 MB max
and freeing 12 MB with each GC. Not a problem.
+---------------
| All other common lisp implementations I tried (clisp, gcl, sbcl)
| works fine with that code.
+---------------
Works fine in CMUCL, too, just maybe noisier than you prefer.
[But you can fix that.]
+---------------
| Does anyone knows what happens with cmucl...
+---------------
CMUCL defaults to *GC-VERBOSE* being T.
+---------------
| and how I can correct it?
+---------------
Two ways:
1. Turn off GC reporting: (SETF *GC-VERBOSE* NIL)
2. Compile the code. The compiler will keep all the intermediate
results in registers, and since none is bigger than a fixnum,
no consing of intermediates happens. Note that compilation is
automatic if you call TIME (*and* you get see how fast it goes):
> (time
(do ((i 1 (+ 1 i)))
((= i 1000) nil)
(do ((j 1 (+ 1 j)))
((= j 1000) nil)
(+ i j))))
; Compiling LAMBDA NIL:
; Compiling Top-Level Form:
; Evaluation took:
; 0.01f0 seconds of real time
; 0.009581f0 seconds of user run time
; 0.0f0 seconds of system run time
; 22,482,898 CPU cycles
; 0 page faults and
; 0 bytes consed.
;
NIL
>
In general, if a Lisp implementation *has* a compiler [as CMUCL
does, as well as GCL, SBCL, CLISP (albeit only to byte-code),
and many others], then *always* compile your code before worrying
about performance...
-Rob
p.s. Sure, you can cut the runtime even more [87%] by peppering
the code with declarations:
> (time
(locally
(declare (optimize (speed 3) (safety 0)))
(do ((i 1 (+ 1 i)))
((= i 1000) nil)
(declare (fixnum i))
(do ((j 1 (+ 1 j)))
((= j 1000) nil)
(declare (fixnum j))
(the fixnum (+ i j))))))
; Compiling LAMBDA NIL:
; Compiling Top-Level Form:
; Evaluation took:
; 0.01f0 seconds of real time
; 0.001371f0 seconds of user run time
; 0.0f0 seconds of system run time
; 3,023,496 CPU cycles
; 0 page faults and
; 0 bytes consed.
;
NIL
>
But why bother in this case?
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607