sionescu / CIM

Common Lisp Implementation Manager
Other
106 stars 11 forks source link

Using compiled script.lisp makes 'cl' faster #18

Open fukamachi opened 10 years ago

fukamachi commented 10 years ago

I suppose the execution time of 'cl' is not a matter for you currently. So, actually, this is not an issue, but I want to share what I found and want to try suggesting something.

What makes 'cl' slow?

You know, 'cl' command is quite slow even the --eval form is a simple one.

$ time cl --eval '(princ (+ 1 2))'
3
cl --eval '(princ (+ 1 2))'  1.27s user 0.38s system 99% cpu 1.658 total

If I add --no-init option and prevent loading Quicklisp, it would be about 10 times faster.

time cl --no-init --eval '(princ (+ 1 2))'
3
cl --no-init --eval '(princ (+ 1 2))'  0.11s user 0.04s system 97% cpu 0.157 total

It takes about 90% of its execution time to just loading Quicklisp.

How can we make it faster?

Seemingly, there's no way to avoid it, but 'cl' command got --core to other load Lisp core file in #17. We can avoid this startup time just by creating a Lisp core file already loaded Quicklisp.

$ time cl --core ~/dumped-cores/sbcl-1.2.1.core --eval '(princ (+ 1 2))'
3
cl --core ~/dumped-cores/sbcl-1.2.1.core --eval   0.11s user 0.04s system 99% cpu 0.149 total

But, it's still slow

Now it runs 10 times faster than before, but it is still slow. 'sbcl' command is still 11 times faster than 'cl' command.

$ time sbcl --core ~/dumped-cores/sbcl-1.2.1.core --noinform --no-sysinit --no-userinit --eval '(princ (+ 1 2))' --eval '(sb-ext:exit)'
3
sbcl --core ~/dumped-cores/sbcl-1.2.1.core --noinform   0.01s user 0.01s system 91% cpu 0.022 total

The difference is came from ~/.cim/lib/script.lisp. 'cl' command always loads it from a source file.

If the source file would be compiled, the execution time would be better. As --load option always use the file, even if there's a fasl file for it. This means 'cl' command compiles & loads ~/.cim/lib/script.lisp every time.

$ cl -c ~/.cim/lib/script.lisp

And made a change to scripts/cl just for trial.

diff --git a/scripts/cl b/scripts/cl
index 1d43f76..e90e975 100755
--- a/scripts/cl
+++ b/scripts/cl
@@ -57,6 +57,9 @@ run_lisp(){

 case "$LISP_IMPL" in
     sbcl*)
+        if [ -f "$CIM_HOME/lib/script.fasl" ]; then
+            load_file="$CIM_HOME/lib/script.fasl"
+        fi
         run_lisp ${use_core+--core} ${use_core+"$lisp_core_file"} --noinform --no-sysinit --no-userinit --non-interactive --load "$load_file" -- "$@"
         ;;
     clisp*)

Then it would be about 3 times faster.

$ time cl --core ~/dumped-cores/sbcl-1.2.1.core --eval '(princ (+ 1 2))'
3
cl --core ~/dumped-cores/sbcl-1.2.1.core --eval   0.04s user 0.03s system 96% cpu 0.066 total

Conclusion

percent reason
90% Quicklisp
6% lib/script.lisp
4% ....

Though 6% looks not a big deal, it is still 4 times slower than 'sbcl' command.

I think "using fasl file" is not so good idea because then we need to manage "fasl" files for each implementation. It makes CIM very complicated.

I'm trying to use 'cl' command as a backend of 'shly' command of Shelly, so I hope 'cl' command is as fast as possible.

Are there any ways to make it faster?

KeenS commented 10 years ago

This is discussed in #10 and @guicho271828 has implemented the compilaton system. Basically, I'm forward to merge the PR but since that patch contains many separated features and require to rewrite many other parts, merging is delayed. Please wait a while.