Subject: Re: TERPRI
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 20 Mar 2004 09:49:02 -0600
Newsgroups: comp.lang.lisp
Message-ID: <Av6dne0z-d5z-sHd3czS-w@speakeasy.net>
David Steuber  <david.steuber@verizon.net> wrote:
+---------------
| In the end, I still think a smaller application will be faster than a
| larger one because of I/O constraints above and beyond the fact that
| a larger application is larger because it does more work.
| 
| I think what I need is to come up with some real profiling data.  It
| is common enough for people to be completely wrong about the time
| cost of code.  
+---------------

You may find some of the results surprising; I certainly did. As I
mentioned elsewhere, I was running some micro-benchmarks on startup
times for "scripts", and comparing CLISP-2.29 and CMUCL-18e produced
some unexpected results [on a 1.855 GHz Mobile Athlon XP 2500+]:

    % cat hello.clisp
    #!/usr/local/bin/clisp
    (format t "hello world!~%")
    % time-hist -n 100 ./hello.clisp
    Timing 100 runs of: ./hello.clisp
       2 0.019
      30 0.020
      68 0.021
    % 

Not bad: ~20-21ms per run. But look at *this*!

    % cat hello.cmucl
    #!/usr/local/bin/cmucl -script
    (format t "hello world!~%")
    % time-hist -n 100 ./hello.cmucl
    Timing 100 runs of: ./hello.cmucl
       1 0.015
      98 0.016
       1 0.017
    % 

It's even slightly faster [though less convenient] if you don't use
the "#!" scripting:

    % cat hello.lisp
    (format t "hello world!~%")
    % time-hist cmucl -quiet -noinit -load test1.lisp -eval "'(quit)'"
    Timing 100 runs of: cmucl -quiet -noinit -load test1.lisp -eval '(quit)'
      97 0.014
       3 0.015
    % 

Note that on this system I always have at least one CLISP process and
at least one CMUCL process running all the time (started at boot time
or login time), so none of the above numbers capture the "first touch"
overhead of either implementation, which is considerable (since the disk
here isn't hyper-fast).

Some things I can think of to explain the direction of the difference,
despite CLISP's bin+core being ~4.2 MB and CMUCL's bin+core being ~21.1 MB,
are that:

1. "/usr/local/bin/clisp" is a tiny wrapper program that actually execs
   "/usr/local/lib/clisp/full/lisp.run", so there is an extra Unix
   "exec()" involved compared to "/usr/local/bin/cmucl" (which is just
   a symlink to "/u/lisp/contrib/cmucl/bin/lisp" [where it happens to
   live here]).
   
2. CMUCL mmap's its core image MAP_PRIVATE, that is, "copy on write",
   which means that copies of the file in the filesystem's memory
   buffer cache can be re-used for other CMUCL processes without
   touching the disk. I can't read German, but from the occasional
   English comments in the CLISP code it *looks* like it's doing the
   same thing, but I can't be sure. Assuming they both do, that tends to
   wipe out any difference in file sizes, since most of both executables
   and images would be in memory all the time anyway.

3. Almost all of the CMUCL core Common Lisp functionality is compiled
   to native x86 code; a goodly amount of the CLISP core is compiled
   to byte-code, which is slower.

The point being that one's choice of CLISP vs. CMUCL for any given
application, say, "scripting", should not be made based on bin+core
size alone. Use the one that works best for you, has the features
you need, etc.


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607