Preface
Several weeks ago, SBCL 2.0.2 updated with a "new" feature called Block Compilation
. This is the first time I hear this term, I go collect some information of this new feature and I found this article.
Questions
After read this article I have several questions:
If I enable this optimization, do I lost the ability of redefine the function
What are the differences between this optimization and
inline
How faster this optimization can achieve
Verification
Let me verify them one by one
If I enable this optimization, do I lost the ability of redefine the function
The answer is yes I can.
(defun foo (x y)
(bar x y))
(defun bar (x y)
(+ x y))
Then I compile whole file and load it in repl:
(compile-file "/Users/BC.lisp" :block-compile t :entry-points nil :output-file "/Users/BC.fasl")
(load "/Users/BC.fasl")
(foo 1 1) ;; => 2
Then I redefine bar
function:
(defun bar () (print "a"))
(foo 1 1) ;; => 2
(bar) ;; => "a"
So I still have ability to redefine function bar
, but even foo
call bar
, the foo
's behavior hasn't been changed because bar
be redefined.
How about I don't enable Block compilation
?
(compile-file "/Users/BC.lisp" :block-compile nil :entry-points nil :output-file "/Users/BC.fasl") ;; turn off Block compilation
(load "/Users/BC.fasl")
(foo 1 1) ;; => 2
(defun bar () (print "a")) ;; redefine bar
(foo 1 1) ;; ERROR
; Evaluation aborted on #<SB-INT:SIMPLE-PROGRAM-ERROR "invalid number of arguments: ~S" {1002751533}>.
As we can see, if I turn off Block compilation
, each time I call foo
, foo
is gonna to call bar
inside. So if I redefine bar
, foo
's behavior has been changed by my redefinition.
What are the differences between this optimization and
inline
I asked this question on SO, here is the post
How faster this optimization can achieve
I always use some stupid way to test productivity -- time
function. So, I use it again:
;;; new file
(defun foo (x y z)
(bar x y z))
(defun bar (x y z)
(max x y z))
Same, compile and load it:
(compile-file "/Users/BC.lisp" :block-compile nil :entry-points nil :output-file "/Users/BC.fasl") ;; turn off Block compilation
(load "/Users/BC.fasl")
(time (loop repeat 3000000 do (foo 1 2 3))) ;; run 3 millions times
Then, I get the result:
Evaluation took:
0.040 seconds of real time
0.040597 seconds of total run time (0.040512 user, 0.000085 system)
102.50% CPU
117,978,902 processor cycles
0 bytes consed
Next, do same thing but turn on Block compilation this time:
(compile-file "/Users/BC.lisp" :block-compile t :entry-points nil :output-file "/Users/BC.fasl")
(load "/Users/BC.fasl")
(time (loop repeat 3000000 do (foo 1 2 3)))
This time, the answer is
Evaluation took:
0.037 seconds of real time
0.037057 seconds of total run time (0.036985 user, 0.000072 system)
100.00% CPU
107,609,083 processor cycles
0 bytes consed
Well, it just a little bit faster. I guess if my function is more complex, it should be much faster than just max
function.