shhyou helped me figure this out; it was really my fault, as I was generating a 
new set!-transformer each time through the loop, instead of a call to a single 
transformer.

  
https://gist.github.com/shhyou/ff5366e8469d4da8f54d262a52744f30#file-bind-it-rkt

Fell in a standard macro trap.

--
William J. Bowman

On Thu, Mar 10, 2022 at 08:49:46PM -0800, 'William J. Bowman' via Racket 
Developers wrote:
> I've extracted a piece of a language implementation here (also attached)
>   https://gist.github.com/wilbowma/87d7e18718e08968cc4b2d003efbff2b
> 
> It provides two implementations of a little language that provides an 
> unbounded
> number of implicit global mutable variables.
> I decided to bind the first 1000 of them because I figure no user would 
> generate
> that many, instead of doing anything clever.
> 
> One method uses `let-syntax` and implements these variables with set!
> transformers, and the other just binds the variables with `let`.
> 
> It seems the version that uses `let-syntax` runs in time directly proportional
> to the number of these variables I decide to bind, i.e., the number of macros 
> I
> introduce via `let-syntax`; about 1ms per variable bound, regardless of 
> whether
> the macros are ever used.
> 
> This behaviour surprised me a lot. Is this expected? 
> 
> -- 
> William J. Bowman
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Racket Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/racket-dev/YirU6gt5MxSnLcvf%40williamjbowman.com.

> #lang racket
> (require (for-syntax racket/syntax))
> 
> #|
> 1,000 fvars; let-syntax implementation
> cpu time: 1162 real time: 1165 gc time: 156
> 
> 10,000 fvars; let-syntax implementation
> cpu time: 10928 real time: 10964 gc time: 1374
> 
> 1,000 fvars; let implementation
> cpu time: 20 real time: 20 gc time: 3
> 
> 10,000 fvars; let implementation
> cpu time: 225 real time: 225 gc time: 54
> |#
> 
> (begin-for-syntax
>   (define current-fvars (make-parameter 10000))
> 
>   (define (bind-fvars s n tail)
>     #`(let-syntax
>           #,(for/list ([i (in-range 0 n)])
>               (with-syntax ([fvar (syntax-local-introduce (format-id #f 
> "fv~a" i))]
>                             [offset i]
>                             [stack s])
>                 #`[fvar (make-set!-transformer
>                          (lambda (stx)
>                            (syntax-case stx ()
>                              [(set! id v)
>                               #`(vector-set! stack offset v)]
>                              [id (identifier? #'id)
>                                  #`(vector-ref stack offset)])))]))
>         #,tail)))
> 
> (define-syntax (my-module stx)
>   (syntax-case stx ()
>     [(_ e ...)
>      (with-syntax ([s #'stack])
>        #`(let ([s (make-vector #,(current-fvars) (void))])
>            #,(bind-fvars #'s (current-fvars) #`(begin e ...))))]))
> 
> (define-namespace-anchor a)
> 
> (displayln "1,000 fvars; let-syntax implementation")
> 
> (time
>  (eval
>   '(begin
>      (begin-for-syntax
>        (current-fvars 1000))
>      (my-module
>       (set! fv0 8)
>       (set! fv1 8)
>       (+ fv0 fv1)))
>   (namespace-anchor->namespace a)))
> 
> (displayln "10,000 fvars; let-syntax implementation")
> 
> (time
>  (eval
>   '(begin
>      (begin-for-syntax
>        (current-fvars 10000))
>      (my-module
>       (set! fv0 8)
>       (set! fv1 8)
>       (+ fv0 fv1)))
>   (namespace-anchor->namespace a)))
> 
> (define-for-syntax (bind-fvars2 n tail)
>   #`(let #,(for/list ([i (in-range 0 n)])
>              (with-syntax ([fvar (syntax-local-introduce (format-id #f "fv~a" 
> i))])
>                #`[fvar (void)]))
>       #,tail))
> 
> (define-syntax (my-module2 stx)
>   (syntax-case stx ()
>     [(_ e ...)
>      (bind-fvars2 (current-fvars) #`(begin e ...))]))
> 
> ;; expansion time increases with the number of let bindings, but not nearly 
> as bad
> ;; expansion time seems to be 1ms per fvar, i.e., per let-syntax?
> 
> (displayln "1,000 fvars; let implementation")
> 
> (time
>  (eval
>   '(begin
>      (begin-for-syntax
>        (current-fvars 1000))
>      (my-module2
>       (set! fv0 8)
>       (set! fv1 8)
>       (+ fv0 fv1)))
>   (namespace-anchor->namespace a)))
> 
> (displayln "10,000 fvars; let implementation")
> (time
>  (eval
>   '(begin
>      (begin-for-syntax
>        (current-fvars 10000))
>      (my-module2
>       (set! fv0 8)
>       (set! fv1 8)
>       (+ fv0 fv1)))
>   (namespace-anchor->namespace a)))

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-dev/YisAyqG3vbsosdna%40williamjbowman.com.

Reply via email to