source-path recording wastes time on quoted lists
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Medium
|
Unassigned |
Bug Description
The test case below shows that EVAL of a call of TIME can be very
slow. This log is from an Opteron running 32-bit linux and SBCL
1.0.43. I had similar results on a Mac (Darwin) running SBCL 1.0.29.
The log shows a slowdown whether we call TEST-TIME or just use its
body. However, evaluation of (print (eq (eval `(time big)) big)) is
fast -- it's something about `(time (quote ,big)) passed to EVAL that
is causing the problem.
By the way, I tried this test with others Lisps on 32-bit Linux (where
I compile functions explicitly for CMUCL, GCL, and Allegro CL). I'm
not seeing this problem with CCL, or (where I'm compiling functions)
with GCL or Allegro CL. I do see it with CMUCL, where I get lots of
GC messages.
lhug-8:~> /p/bin/sbcl-1.0.43
This is SBCL 1.0.43, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (declaim (optimize (compilation-speed 0) (speed 3) (space 0) (safety 0)))
* (defun make-tree (n acc)
(cond ((zerop n) acc)
(t (make-tree (1- n) (cons acc acc)))))
MAKE-TREE
* (defconstant big (make-tree 10000 nil))
BIG
* (defun test-time () (print (eq (eval `(time (quote ,big))) big)))
TEST-TIME
* (let (old new)
(setq old (get-internal-
(test-time)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
4,529 processor cycles
0 bytes consed
T
4.765
* (let (old new)
(setq old (get-internal-
(print (eq (eval `(time (quote ,big))) big))
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
Evaluation took:
0.000 seconds of real time
0.000000 seconds of total run time (0.000000 user, 0.000000 system)
100.00% CPU
4,092 processor cycles
0 bytes consed
T
4.725
* (defun test-no-time () (print (eq (eval `(quote ,big)) big)))
TEST-NO-TIME
* (let (old new)
(setq old (get-internal-
(test-no-time)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
0.0
* (let (old new)
(setq old (get-internal-
(print (eq (eval `(quote ,big)) big))
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
0.0
*
.....
Additional info requested:
lhug-8:~> uname -a
Linux lhug-8.
lhug-8:~> /p/bin/sbcl-1.0.43 --version
SBCL 1.0.43
lhug-8:~> /p/bin/sbcl-1.0.43
This is SBCL 1.0.43, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* *features*
(:ANSI-CL :COMMON-LISP :SBCL :SB-DOC :SB-TEST :SB-LDB :SB-PACKAGE-LOCKS
:SB-UNICODE :SB-EVAL :SB-SOURCE-
:LINUX :SB-THREAD :LARGEFILE :GENCGC :STACK-
:C-STACK-
:RAW-INSTANCE-
:STACK-
:CYCLE-COUNTER :INLINE-CONSTANTS :MEMORY-
:OS-PROVIDES-
:OS-PROVIDES-
*
Changed in sbcl: | |
status: | Fix Committed → Fix Released |
Sorry; this bug isn't only about TIME after all. It appears to be about a
slowdown in EVAL when there are LET-bindings in the form, as is
illustrated by the log just below (both for lexical and special
variables, as long as at least one variable is being bound). The
platform is as before: 32-bit Linux running SBCL 1.0.43. Again, CMUCL
shows the same slowdown; but GCL, Allegro CL, and CCL do not.
lhug-8:~> /p/bin/sbcl-1.0.43 www.sbcl. org/>.
This is SBCL 1.0.43, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (declaim (optimize (compilation-speed 0) (speed 3) (space 0) (safety 0)))
* (defun make-tree (n acc)
(cond ((zerop n) acc)
(t (make-tree (1- n) (cons acc acc)))))
MAKE-TREE
* (defconstant big (make-tree 10000 nil))
BIG
* (defun test ()
(print (eq (eval `(let ((x 17)) (cdr (cons x (quote ,BIG)))))
big)))
TEST real-time) ) real-time) ) time-units- per-second) ))
* (let (old new)
(setq old (get-internal-
(test)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
4.762
* (defvar *my-special* nil)
*MY-SPECIAL*
* (defun test2 ()
(print (eq (eval `(let ((*my-special* 17)) (quote ,BIG)))
big)))
TEST2 real-time) ) real-time) ) time-units- per-second) ))
* (let (old new)
(setq old (get-internal-
(test2)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
4.764
* (defun test-fast ()
(print (eq (eval `(quote ,BIG))
big)))
TEST-FAST real-time) ) real-time) ) time-units- per-second) ))
* (let (old new)
(setq old (get-internal-
(test-fast)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
0.0
* (defun test3 ()
(print (eq (eval `(let ((x 17)) (declare (ignore x)) (quote ,BIG)))
big)))
TEST3 real-time) ) real-time) ) time-units- per-second) ))
* (let (old new)
(setq old (get-internal-
(test3)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
4.751
* (defun test-fast2 ()
(print (eq (eval `(let () (quote ,BIG)))
big)))
TEST-FAST2 real-time) ) real-time) ) time-units- per-second) ))
* (let (old new)
(setq old (get-internal-
(test-fast2)
(setq new (get-internal-
(/ (- new old) (* 1.0 internal-
T
0.0
*