Sounds like Racket is using a "deep binding" strategy rather than "shallow binding". I expect that SBCL uses shallow. On Aug 16, 2013 5:10 AM, "Matthew Flatt" <[email protected]> wrote:
> At Fri, 16 Aug 2013 13:59:55 +0400, Roman Klochkov wrote: > > > > I compared parameterize with lexical var > > ---- > > > (require rackunit) > > > (define my-parameter (make-parameter (box 0))) > > > (time > > (parameterize ([my-parameter (box 0)]) > > (for ([x (in-range 10000000)]) > > (set-box! (my-parameter) > > (add1 (unbox (my-parameter))))) > > (check-equal? (unbox (my-parameter)) 10000000))) > > cpu time: 3578 real time: 3610 gc time: 0 > > > (time > > (let ([my-parameter (box 0)]) > > (for ([x (in-range 10000000)]) > > (set-box! my-parameter > > (add1 (unbox my-parameter)))) > > (check-equal? (unbox my-parameter) 10000000))) > > cpu time: 47 real time: 47 gc time: 0 > > ---- > > > > 100 times difference! > > > > The same experiment with Common Lisp (SBCL): > > ---- > > CL-USER> (setf *a* (list 0)) > > (0) > > CL-USER> (time (progn (loop :for i :from 0 :below 10000000 > > :do (setf (car *a*) (+ 1 (car *a*)))) (= (car *a*) > 10000000))) > > Evaluation took: > > 0.063 seconds of real time > > 0.062500 seconds of total run time (0.062500 user, 0.000000 system) > > 98.41% CPU > > 172,464,541 processor cycles > > 0 bytes consed > > > > T > > CL-USER> (let ((a (list 0))) (time (loop :for i :from 0 :below 10000000 > > :do (setf (car a) (+ 1 (car a))))) (= (car a) 10000000)) > > > > Evaluation took: > > 0.047 seconds of real time > > 0.046875 seconds of total run time (0.046875 user, 0.000000 system) > > 100.00% CPU > > 132,098,942 processor cycles > > 0 bytes consed > > > > T > > ---- > > Only 1.5 times. > > > > Is it undesirable to use parameterize as replacement for common lisp > special > > variables? What is it designed for then? > > Parameters in Racket are grouped together in a an extra layer called a > "parameterization", which enables capture of the current values of all > parameters. For example, when a new thread is created in Racket, then > the new inherits all of the current parameter values from the creating > thread. A lack of cleverness in that layer is probably the main effect > on performance in yuor example. > > Using a raw, symbol-keyed continuation mark would be closer to a Common > Lisp special variable, I think. On my machine: > > ;; parameter > > (time > (parameterize ([my-parameter (box 0)]) > (for ([x (in-range 10000000)]) > (set-box! (my-parameter) > (add1 (unbox (my-parameter))))) > (check-equal? (unbox (my-parameter)) 10000000))) > cpu time: 2539 real time: 2537 gc time: 0 > > ;; direct > > (time > (let ([my-parameter (box 0)]) > (for ([x (in-range 10000000)]) > (set-box! my-parameter > (add1 (unbox my-parameter)))) > (check-equal? (unbox my-parameter) 10000000))) > cpu time: 45 real time: 45 gc time: 0 > > ;; raw continuation mark: > > (time > (let ([my-parameter > (lambda () > (continuation-mark-set-first #f 'my-parameter))]) > (with-continuation-mark > 'my-parameter > (box 0) > (begin > (for ([x (in-range 10000000)]) > (set-box! (my-parameter) > (add1 (unbox (my-parameter))))) > (check-equal? (unbox (my-parameter)) 10000000))))) > cpu time: 244 real time: 243 gc time: 0 > > That's still a fact of 5 difference. I expect that dynamic binding and > special variables have played a more prominent role in Common Lisp than > parameters or even continuation-mark lookup in Racket, and so it would > make sense that more work has been done in the SBCL to make them fast. > > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users >
____________________ Racket Users list: http://lists.racket-lang.org/users

