I forgot to mention this earlier, but it might be enlightening to run the two versions of the program with the `PLTSTDERR` environment variable set to "error debug@GC" to see GC debug messages. For example:
env PLTSTDERR='error debug@GC' racket flvector-to-coordinates-string.rkt >/dev/null Bogdan Popa writes: > Hi Alessandro, > > Here is a version of your program that is about 30 times faster on my > machine (9s -> 300ms): > > #lang racket/base > > (require racket/flonum > racket/format > racket/port) > > (define (xy-vectors->string x-vec y-vec) > (call-with-output-string > (lambda (out) > (for ([i (in-naturals)] > [x (in-flvector x-vec)] > [y (in-flvector y-vec)]) > (unless (zero? i) > (write-char #\space out)) > (write-string (~r x #:precision 1) out) > (write-char #\, out) > (write-string (~r y #:precision 1) out))))) > > (time > (let ([x (make-flvector 100000)] > [y (make-flvector 100000)]) > (xy-vectors->string x y))) > > All the calls to `string-append` in your original program end up > allocating larger and larger strings and then immediately discarding > them on subsequent iterations, which is costly over many iterations. > > Hope that helps, > Bogdan > > Alessandro Motta writes: > >> Hi racket-users! >> >> I've recently become interested in Lisp/Scheme and have started to hack >> in Racket. The excellent documentation, the fast integrated search, and >> DrRacket have made that a real pleasure. >> >> Thank you for that! >> >> I've been working on a tool to convert notes from the reMarkable 2 >> tablet to SVG files. At the core is the conversion of (x, y) coordinate >> pairs from two `flvector`s to a string of the form "x1,y1 x2,y2 x3,y3". >> >> ``` >> (define (xy->string x y) >> (string-append >> (~r x #:precision 1) "," >> (~r y #:precision 1))) >> >> (define (xy-vectors->string x-vec y-vec) >> (for/fold ((coordinates "") >> (separator "") >> #:result coordinates) >> ((x (in-flvector x-vec)) >> (y (in-flvector y-vec))) >> (values (string-append >> coordinates >> separator >> (xy->string x y)) >> " "))) >> ``` >> >> This is currently the bottleneck for large conversion jobs. >> >> Profiling these functions with `profile-flame-graph` resulted in >> https://gist.githubusercontent.com/amotta/cfe4b19e24455af219521c9e94455c67/raw/dbbc87bd2f6dd4e27c33831749baa90fffdaed55/flvector-to-coordinates-string-flamegraph.svg >> >> The full profiling script is available at >> https://gist.github.com/amotta/e76197082bb1bf63538ede01872917f3 >> >> Roughly 90% of time is spent in `contract/private/arrow-val-first.rkt`. >> Based on my very limited understanding of Racket, it seems that ~38% of >> time is spent handling keyword arguments (presumably `#:precision 1`?). >> The `catnp` function (the conversion from flonum to string, I think) >> takes up only ~11% of time. >> >> Is this interpretation of the flame graph correct? If so, are there any >> obvious blunders on my part? Any ideas for how to speed up this code? >> >> >> Best wishes, >> Alessandro -- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/m2sg13crgy.fsf%40defn.io.

