@oscar88 has joined the channel
by “different language” do you mean languages implemented atop of Racket?
@laurent.orseau Interestingly, gen:stream
, which is much simpler to use, is even faster than define-sequence-syntax
+ :do-in
which is supposed be to faster…
#lang racket
(define-sequence-syntax in-list+rest
(lambda () #'in-list+rest/proc)
(lambda (stx)
(syntax-case stx ()
[[(x r) (_ lst)]
#'[(x r)
(:do-in
([(l) lst])
(unless (list? l)
(raise-argument-error 'in-list+rest "list?" l))
([l l])
(not (null? l))
([(x r) (values (car l) (cdr l))])
#true
#true
[r])]]
[_ #f])))
(define (in-list+rest/proc l)
(for/list ([(x r) (in-list+rest l)]) (list x r)))
(struct in-list+rest** (xs)
#:methods gen:stream
[(define (stream-empty? self)
(null? (in-list+rest**-xs self)))
(define (stream-first self)
(define xs (in-list+rest**-xs self))
(list (car xs) (cdr xs)))
(define (stream-rest self)
(in-list+rest** (cdr (in-list+rest**-xs self))))])
(define (in-list+rest* xs)
(unless (list? xs)
(raise-argument-error 'in-list+rest* "list?" xs))
(in-list+rest** xs))
(define xs (range 1000000))
(time (for ([x (in-list+rest xs)])
x))
(time (for ([x (in-list+rest* xs)])
x))
This outputs:
cpu time: 396 real time: 433 gc time: 309
cpu time: 106 real time: 111 gc time: 2
in Racket, and
cpu time: 233 real time: 236 gc time: 194
cpu time: 97 real time: 101 gc time: 0
in Racket CS.
Woah, this is very surprising to me. How come then?
(it’s also very cool :slightly_smiling_face: )
I don’t know!
Oh, actually, what’s going on seems to be that there’s a lot of GC activity going on in in-list+rest
.
What’s weird is that swapping lines doesn’t help.
Does it help to remove the list?
check? (speed-wise that is not gc-wise)
The list?
check in both versions are at the top-level, so it’s not an issue. But if you call list?
on every iteration, there will be a clear performance degradation in Racket CS. I just reported the issue at https://github.com/racket/racket/issues/3109
I am surprised by the difference. If anything I would have guessed at the opposite times.
Can you add a (collect-garbage) before each loop?
I just did that last minute lol
On Racket CS, the difference disappears. On Racket BC, define-sequence-syntax
+ :do-in
is still far worse.
I guess it depends when the gc happens then
so that means the :do version does a lot of gc, but the struct one doesn’t?
Yep
The gen:stream
version doesn’t trigger the GC as much.
There must be some copying going on, that’s mostly optimized away, but not entirely?
I tried swapping the two variants around, and it is always the case that :do-in
takes the GC hit.
How does gen:stream work under the hood?
I don’t know…
Can you compare with the bare let loop variant I posted before?
It shouldn’t trigger the GC unnecessarily I suppose
@sorawee I don’t think your :do-in
syntax is being used at all. You’re looking for uses of the form [(x r) (_ lst)]
, but your use site has the form [x (in-list+rest xs)]
, which doesn’t match the pattern. So it falls back to using in-list+rest/proc
, which has to allocate the whole list. If you fix that issue, I expect the :do-in
version to be far more efficient than the one using gen:stream
.
Ahhh
Yep, you are absolutely right. When I invoke it correctly, the result is:
cpu time: 105 real time: 107 gc time: 8
cpu time: 5 real time: 6 gc time: 0
where the below one is :do-in
.
Dumb question possibly, but in the Racket FFI can I send a Racket function into C as a callback?
Yes.
How? Do I just pass it as an argument to a function that expects a _fun?
Will racket wrap it with the relevant type checking?
@pavpanchekha Check _cprocedure https://docs.racket-lang.org/foreign/foreign_procedures.html
Also ffi-callback
@pavpanchekha basically, it just works. @soegaard2 usually you don’t need to use _cprocedure
, you can just use _fun
.
Thanks - it has been a while since I used it. I keep forgetting the details. Too bad dyoo never finished his tutorial.
Also I keep forgetting Asumu wrote one: http://prl.ccs.neu.edu/blog/2016/06/27/tutorial-using-racket-s-ffi/
Nice!
Classic Racket
In Typed Racket how can I require in syntax from an untyped module?
(specifically, what is the syntax to require in include-template
from web-server/templates
?)
Good catch @lexi.lambda!