[comp.lang.lisp] Loop speeds

wilk@fife.cs.cornell.edu (Michael Wilk) (10/15/90)

After puzzling over the results of the speed tests I performed on the "mirror"
program, I discovered a disturbing discrepancy between the loop macro and the
mapping functions.  Consider the performance gap between running these two
versions of function foo on a list of 30000 items:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(defun foo (x)
  (loop for item in x
	collect (atom item)))

Elapsed Real Time = 7.86 seconds
Total Run Time    = 7.84 seconds
User Run Time     = 7.84 seconds
System Run Time   = 0.00 seconds
Process Page Faults    =          7
Dynamic Bytes Consed   =          0
Ephemeral Bytes Consed =    240,176

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(defun foo (x)
  (mapcar #'atom x))

Elapsed Real Time = 0.14 seconds
Total Run Time    = 0.14 seconds
User Run Time     = 0.14 seconds
System Run Time   = 0.00 seconds
Process Page Faults    =          0
Dynamic Bytes Consed   =          0
Ephemeral Bytes Consed =    240,008

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

(These tests were run in Lucid Common Lisp on a DECstation 5000.  The functions
were compiled and optimized for speed.  I ran the tests several times and chose
the run with the fewest page faults.  The predicate #'atom was chosen
arbitrarily.)

Would you conclude from this that one should always use mapcar instead of
loop/for/collect in simple cases?  Why isn't macro expansion smarter?

-Michael Wilk (wilk@cs.cornell.edu)

eb@sunvalleymall.lucid (Eric Benson) (10/16/90)

In article <47103@cornell.UUCP> wilk@fife.cs.cornell.edu (Michael Wilk) writes:

   After puzzling over the results of the speed tests I performed on the "mirror"
   program, I discovered a disturbing discrepancy between the loop macro and the
   mapping functions.  Consider the performance gap between running these two
   versions of function foo on a list of 30000 items:

   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   (defun foo (x)
     (loop for item in x
	   collect (atom item)))

   Elapsed Real Time = 7.86 seconds
   Total Run Time    = 7.84 seconds
   User Run Time     = 7.84 seconds
   System Run Time   = 0.00 seconds
   Process Page Faults    =          7
   Dynamic Bytes Consed   =          0
   Ephemeral Bytes Consed =    240,176

   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   (defun foo (x)
     (mapcar #'atom x))

   Elapsed Real Time = 0.14 seconds
   Total Run Time    = 0.14 seconds
   User Run Time     = 0.14 seconds
   System Run Time   = 0.00 seconds
   Process Page Faults    =          0
   Dynamic Bytes Consed   =          0
   Ephemeral Bytes Consed =    240,008

   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   (These tests were run in Lucid Common Lisp on a DECstation 5000.  The functions
   were compiled and optimized for speed.  I ran the tests several times and chose
   the run with the fewest page faults.  The predicate #'atom was chosen
   arbitrarily.)

   Would you conclude from this that one should always use mapcar instead of
   loop/for/collect in simple cases?  Why isn't macro expansion smarter?

   -Michael Wilk (wilk@cs.cornell.edu)

It appears that you have made a mistake in your testing.  In looking
at the code generated by our compiler for these two function there is
hardly any difference.  There is virtually no difference in speed
between the two.  My best guess is that you ran the first function
interpreted and the second one compiled.  That's the only explanation
for a factor of 56 difference in speed!

eb@lucid.com 	           	 	Eric Benson
415/329-8400 x5523                      Lucid, Inc.
Telex 3791739 LUCID                     707 Laurel Street
Fax 415/329-8480                        Menlo Park, CA 94025