From: Matt K. <kau...@cs...> - 2007-01-10 05:20:47
|
Hello -- I have recently tried an experiment with a program I'm working on (ACL2) in which I avoid explicit calls to compile-file, loading .lisp source files instead of the resulting .fasl files before saving an image. In SBCL 1.0 on Ubuntu, the program's regression suite ran significantly slower when I avoided compile-file (using the same unloaded machine both times). This surprised me, since my understanding is that SBCL always compiles. I did a similar experiment with OpenMCL and found no such slowdown (in fact I got a slight speedup by avoiding the compile-file calls). Here are the SBCL time results. With explicit compile-file: 20300.204u 246.139s 5:44:54.95 99.2% 0+0k 0+0io 0pf+0w Without explicit compile-file: 23021.082u 224.146s 6:30:23.08 99.2% 0+0k 0+0io 0pf+0w Here is the optimize declaim form, which is evaluated before the loading or compiling source files. (declaim (optimize #+(or cmu sbcl lucid lispworks) (compilation-speed 0) #+lispworks (debug 0) #+cmu (extensions:inhibit-warnings 3) #+sbcl (sb-ext:inhibit-warnings 3) (speed 3) (space #+cmu 1 #-cmu 0) (safety 0))) Any thoughts on what's going on? Is it something as simple but low-level as locality of code or the like? By the way, I found in an earlier version that a type error was missed when loading .fasl files but was caught when loading .lisp files, so I'm wondering if some optimization is missing when loading .lisp files. If so, then my model that compile-file is superfluous for SBCL is wrong (well, it's wrong of course based on the timing results). Thanks -- -- Matt Kaufmann |
From: Juho S. <js...@ik...> - 2007-01-14 21:59:55
|
Matt Kaufmann <kau...@cs...> writes: > Hello -- > > I have recently tried an experiment with a program I'm working on > (ACL2) in which I avoid explicit calls to compile-file, loading .lisp > source files instead of the resulting .fasl files before saving an > image. In SBCL 1.0 on Ubuntu, the program's regression suite ran > significantly slower when I avoided compile-file (using the same > unloaded machine both times). This surprised me, since my > understanding is that SBCL always compiles. While loading a source file does compile the code, it's not exactly equivalent to a COMPILE-FILE followed by loading the fasl. For example, an implementation is allowed to assume that any calls to a function F in the file where it is defined refer to that exact definition of F, unless F has been declared as NOTINLINE. A conforming program may not redefine F elsewhere. The SBCL file compiler takes some advantage of this for type inference, while LOAD doesn't. -- Juho Snellman |
From: Thomas F. B. <tbu...@gm...> - 2007-01-15 09:33:18
|
On 15 Jan 2007 00:00:07 +0200, Juho Snellman <js...@ik...> wrote: > Matt Kaufmann <kau...@cs...> writes: > > Hello -- > > > > I have recently tried an experiment with a program I'm working on > > (ACL2) in which I avoid explicit calls to compile-file, loading .lisp > > source files instead of the resulting .fasl files before saving an > > image. In SBCL 1.0 on Ubuntu, the program's regression suite ran > > significantly slower when I avoided compile-file (using the same > > unloaded machine both times). This surprised me, since my > > understanding is that SBCL always compiles. > > While loading a source file does compile the code, it's not exactly > equivalent to a COMPILE-FILE followed by loading the fasl. > > For example, an implementation is allowed to assume that any calls to > a function F in the file where it is defined refer to that exact > definition of F, unless F has been declared as NOTINLINE. A conforming > program may not redefine F elsewhere. The SBCL file compiler takes > some advantage of this for type inference, while LOAD doesn't. The OP should be able to approximate compile-file with something like: (with-compilation-unit () (let ((sb-ext:*derive-function-types* t)) (load "foo.lisp"))) Although to get the most out of the type inferencer, you should really do something more like: (let ((*derive-function-types* t)) (handler-bind ((error #'muffle-warning) (warning #'muffle-warning) (compiler-note #'muffle-warning)) (compile-file "foo.lisp")) (load (compile-file "foo.lisp"))) |
From: Matt K. <kau...@cs...> - 2007-01-15 01:55:27
|
Thank you very much for the helpful reply, which makes sense. But it raises another question. You say: A conforming program may not redefine F elsewhere. The SBCL file compiler takes some advantage of this for type inference, while LOAD doesn't. The first of these sentences puts forth a notion of "conforming" that seems to contradict this passage from the end of Section 5.3.1 ("Defining Named Functions") of CLtL 2: It is permissible to use defun to redefine a function, to install a corrected version of an incorrect definition, for example. It is permissible to redefine a macro as a function. It is an error to attempt to redefine the name of a special form (see table 5-1) as a function. In particular, suppose I define functions F and G, where G calls F, and then I redefine F with a different return type, where G (still) calls F without error. Are you saying that because of type inference, if the initial definitions of F and G are in a compiled file then I could get an error when calling G after redefining F? Thanks -- -- Matt Sender: js...@va... Cc: sbc...@li... From: Juho Snellman <js...@ik...> Date: 15 Jan 2007 00:00:07 +0200 X-SpamAssassin-Status: No, hits=-2.6 required=5.0 X-UTCS-Spam-Status: No, hits=-312 required=200 Matt Kaufmann <kau...@cs...> writes: > Hello -- > > I have recently tried an experiment with a program I'm working on > (ACL2) in which I avoid explicit calls to compile-file, loading .lisp > source files instead of the resulting .fasl files before saving an > image. In SBCL 1.0 on Ubuntu, the program's regression suite ran > significantly slower when I avoided compile-file (using the same > unloaded machine both times). This surprised me, since my > understanding is that SBCL always compiles. While loading a source file does compile the code, it's not exactly equivalent to a COMPILE-FILE followed by loading the fasl. For example, an implementation is allowed to assume that any calls to a function F in the file where it is defined refer to that exact definition of F, unless F has been declared as NOTINLINE. A conforming program may not redefine F elsewhere. The SBCL file compiler takes some advantage of this for type inference, while LOAD doesn't. -- Juho Snellman |
From: Alexey D. <ade...@to...> - 2007-01-15 03:47:22
|
Hello, Juho Snellman writes: > For example, an implementation is allowed to assume that any calls to > a function F in the file where it is defined refer to that exact > definition of F, unless F has been declared as NOTINLINE. Yes. > A conforming > program may not redefine F elsewhere. Well, it's better to say that if F is redefined, all its "evident" callers in the same file should be redefined too. Matt Kaufmann <kau...@cs...> writes: > In particular, suppose I define functions F and G, where G calls F, > and then I redefine F with a different return type, where G (still) > calls F without error. Are you saying that because of type inference, > if the initial definitions of F and G are in a compiled file then I > could get an error when calling G after redefining F? Yes. See CLHS 3.2.2.3 "Semantic Constraints". -- Regards, Alexey Dejneka "Alas, the spheres of truth are less transparent than those of illusion." -- L.E.J. Brouwer |
From: Matt K. <kau...@cs...> - 2007-01-15 14:32:02
|
Thank you for that pointer to HyperSpec Section 3.2.2.3! -- Matt Cc: sbc...@li... From: Alexey Dejneka <ade...@to...> Date: Mon, 15 Jan 2007 06:47:04 +0300 X-SpamAssassin-Status: No, hits=-2.5 required=5.0 X-UTCS-Spam-Status: No, hits=-170 required=200 Hello, Juho Snellman writes: > For example, an implementation is allowed to assume that any calls to > a function F in the file where it is defined refer to that exact > definition of F, unless F has been declared as NOTINLINE. Yes. > A conforming > program may not redefine F elsewhere. Well, it's better to say that if F is redefined, all its "evident" callers in the same file should be redefined too. Matt Kaufmann <kau...@cs...> writes: > In particular, suppose I define functions F and G, where G calls F, > and then I redefine F with a different return type, where G (still) > calls F without error. Are you saying that because of type inference, > if the initial definitions of F and G are in a compiled file then I > could get an error when calling G after redefining F? Yes. See CLHS 3.2.2.3 "Semantic Constraints". -- Regards, Alexey Dejneka "Alas, the spheres of truth are less transparent than those of illusion." -- L.E.J. Brouwer |