I've done a few experiments with a easy version of <member>, that
never has a third argument. (It's wrong, but it's useful to estimate
how much better the final version could be.)

https://github.com/gus-massa/racket/commit/cd35e0dc3db474f8dc31fea170d1bc2900f2e338

I simplified the use of the macros, but I'm not sure that it's
necessary. The main improvement comes from using
begin-encourage-inline, so <member> can be inlined and then the
optimizer can see the (equal? x 'symbol) and transform it to (eq? x
'symbol).

A typical run of:

#lang racket
(require racket/private/member2)
(define l (make-list 5000 'x))
; normal version
(time (for ((i 10000)) (memq 'y l)))
(time (for ((i 10000)) (member 'y l)))
; inlinable version
(time (for ((i 10000)) (memq2 'y l)))
(time (for ((i 10000)) (member2 'y l)))

;=>

cpu time: 764 real time: 873 gc time: 0
cpu time: 5148 real time: 5368 gc time: 0
cpu time: 905 real time: 1041 gc time: 0
cpu time: 2293 real time: 2689 gc time: 0


Analyzing the decompiled version, the for loop is partially "unrolled"
and one half of the times the <member> function is inlined and the
other half of the times it is not inlined. (The pattern is
YYNNYYNNYYNN...) So half of them are fast and half of them are slow,
and the time is close to the average.

This is caused because the internal inlining fuel is not enough to
inline all the instances of member. The same fuel is used for
something similar to loop unrolling, so the pattern is strange. (I
think that more fuel would change the pattern to YYYYYNNYYYYYNN...)

One possible solution is to inline <member> before unrolling the loop.
I think that there are some tricks in the current Racket version that
try to do this when the loop is big, but this is a small loop. But I'm
not sure how this change would affect other code and how difficult
this is.

(Loops are difficult to optimize. Somewhat related: "loop
optimizations in guile"
http://wingolog.org/archives/2015/07/28/loop-optimizations-in-guile )

Gustavo

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to