Date: Mon, 17 Aug 2009 11:04:26 -0400 From: Marc Feeley feeley@iro.umontreal.ca
Are you saying that Scheme48 does not adhere to that Lisp philosophy? I thought Scheme48 supported "live debugging" and that it was the default execution mode. Does the debugger rely on eval? What happens when an exception is raised at run time?
The REPL (or `command processor', `development environment', &c.) is a program just like any other. The REPL uses EVAL, and knows about the environments of (some of) Scheme48's internals, including the REPL's environments (i.e. the environments in which the REPL's source code were compiled) -- that is, the REPL is reified. If you run your programs under the REPL, it will establish condition handlers that cause the debugger to be entered, and all the environments of your program, and any libraries in Scheme48, will be available. But the REPL and the database of your program's global variables aren't built-in to the compiler or to the virtual machine or to the run-time system -- you get what you ask for. If you make your program not to run under the REPL (and don't establish condition handlers that will enter the REPL), then you won't get the REPL.
The point isn't that Scheme48 fails to be adhere to any philosophy of Lisp -- the point is that Scheme48 is a configurable system of parts, not a monolith of global databases as many other Scheme systems are, and as Common Lisp is mandated to be. Fortunately, Scheme is not mandated thus. So for Scheme48, shrinking images is not a matter of going to the extra effort of walking through the global databases and destroying links that you don't want (`tree-shaking'); it's only a matter of specifying what you do want, and then anything not required by that will be omitted anyway.
On my MacBook Pro I checked the size of the runtime system of Scheme48 and Gambit and there is in fact very little difference (scheme48.image=2.7MB and gsi=3.3MB). Also, when executing (let loop () (loop)) the ps program reveals that Scheme48 has a RSS of 6.4MB and Gambit has a RSS of 2.4MB. So at execution time, for a small program, Scheme48 seems to take 2.5 times as much memory as Gambit.
If you evaluate (LET LOOP () (LOOP)) in the REPL, all of the REPL and libraries will remain in the image. If you build a new image that only evaluates (LET LOOP () (LOOP)), it will be much smaller:
,build (lambda (arguments) (let loop () (loop))) foo.image
% ls -lh foo.image -rw-r--r-- 1 riastradh riastradh 740K Aug 17 12:15 foo.image
The 740K consists mostly of the run-time system, which is initialized in images created with the ,BUILD command -- starting the thread scheduler, enabling interrupts in the virtual machine, establishing the dynamic environment for the current input and output ports, &c. This can be omitted, too:
,open write-images (write-image "bar.image" (lambda arguments (let loop () (loop))) "")
% ls -lh bar.image -rw-r--r-- 1 riastradh riastradh 14K Aug 17 12:19 bar.image
(There is still a bit of extra gunk in this image due to the FFI. Before Scheme48's current FFI, bar.image would have been even smaller; e.g., in Scheme48 0.36, the above call yields a baz.image of only 148 bytes.)
How much heap space Scheme48 allocates is a run-time option which doesn't change by default (unless the image is too large for the default heap space). And of course Scheme48 is based on a virtual machine, all of which is loaded into memory; in this respect Gambit has a theoretical advantage, because there is no (run-time) virtual machine needed to interpret its compiled code.