oscar88
2020-4-20 10:47:49

@oscar88 has joined the channel


shu--hung
2020-4-20 11:26:20

by “different language” do you mean languages implemented atop of Racket?


sorawee
2020-4-20 12:17:07

@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.


laurent.orseau
2020-4-20 12:24:53

Woah, this is very surprising to me. How come then?


laurent.orseau
2020-4-20 12:25:10

(it’s also very cool :slightly_smiling_face: )


sorawee
2020-4-20 12:27:49

I don’t know!


sorawee
2020-4-20 12:37:09

Oh, actually, what’s going on seems to be that there’s a lot of GC activity going on in in-list+rest.


sorawee
2020-4-20 12:38:23

What’s weird is that swapping lines doesn’t help.


soegaard2
2020-4-20 12:39:21

Does it help to remove the list? check? (speed-wise that is not gc-wise)


sorawee
2020-4-20 12:39:46

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


soegaard2
2020-4-20 12:46:48

I am surprised by the difference. If anything I would have guessed at the opposite times.


laurent.orseau
2020-4-20 12:53:35

Can you add a (collect-garbage) before each loop?


sorawee
2020-4-20 12:53:47

I just did that last minute lol


sorawee
2020-4-20 12:54:15

On Racket CS, the difference disappears. On Racket BC, define-sequence-syntax + :do-in is still far worse.


laurent.orseau
2020-4-20 12:55:06

I guess it depends when the gc happens then


laurent.orseau
2020-4-20 12:55:32

so that means the :do version does a lot of gc, but the struct one doesn’t?


sorawee
2020-4-20 12:55:37

Yep


sorawee
2020-4-20 12:56:04

The gen:stream version doesn’t trigger the GC as much.


laurent.orseau
2020-4-20 12:56:10

There must be some copying going on, that’s mostly optimized away, but not entirely?


sorawee
2020-4-20 12:56:32

I tried swapping the two variants around, and it is always the case that :do-in takes the GC hit.


soegaard2
2020-4-20 12:56:41

How does gen:stream work under the hood?


sorawee
2020-4-20 12:56:57

I don’t know…


laurent.orseau
2020-4-20 12:58:04

Can you compare with the bare let loop variant I posted before?


laurent.orseau
2020-4-20 12:58:16

It shouldn’t trigger the GC unnecessarily I suppose


lexi.lambda
2020-4-20 16:01:04

@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.


sorawee
2020-4-20 16:01:22

Ahhh


sorawee
2020-4-20 16:35:05

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.


pavpanchekha
2020-4-20 20:16:54

Dumb question possibly, but in the Racket FFI can I send a Racket function into C as a callback?


soegaard2
2020-4-20 20:23:38

Yes.


pavpanchekha
2020-4-20 20:46:48

How? Do I just pass it as an argument to a function that expects a _fun?


pavpanchekha
2020-4-20 20:47:15

Will racket wrap it with the relevant type checking?


soegaard2
2020-4-20 20:49:48

soegaard2
2020-4-20 20:50:11

soegaard2
2020-4-20 20:51:07

Also ffi-callback


samth
2020-4-20 21:03:45

@pavpanchekha basically, it just works. @soegaard2 usually you don’t need to use _cprocedure, you can just use _fun.


soegaard2
2020-4-20 21:04:53

Thanks - it has been a while since I used it. I keep forgetting the details. Too bad dyoo never finished his tutorial.


soegaard2
2020-4-20 21:05:33

pavpanchekha
2020-4-20 21:55:03

Nice!


pavpanchekha
2020-4-20 21:55:07

Classic Racket


dan.ml.901
2020-4-21 00:08:04

In Typed Racket how can I require in syntax from an untyped module?


dan.ml.901
2020-4-21 00:08:44

(specifically, what is the syntax to require in include-template from web-server/templates?)


laurent.orseau
2020-4-21 06:14:05

Good catch @lexi.lambda!