[racket] Style and Performance question

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Mon May 9 23:37:25 EDT 2011

On Mon, May 9, 2011 at 10:25 PM, Sam Tobin-Hochstadt <samth at ccs.neu.edu> wrote:
> On Mon, May 9, 2011 at 11:19 PM, Robby Findler
> <robby at eecs.northwestern.edu> wrote:
>> Even without typed racket, this:
>>
>> (define (my-sqrt y)
>>  (let loop [(x (/ y 2.0))]
>
>> is much faster than this:
>>
>> (define (my-sqrt y)
>>  (let loop [(x (/ y 2))]
>
> Yes, this is one of the optimizations TR does.  :)

It is not a meaning preserving transformation to turn the 2 into a 2.0
in this function, I don't think.

Also, Matthias explicitly wrote "2.0" in the tr version. He didn't
show the other version, but my timing results suggest he wrote "2" in
the other one (and Patrick certainly did).

> As to why TR is so much faster on this program: this is exactly the
> sort of program that TR excels at -- generic arithmetic on floats,
> which we can turn into fast machine instructions.  You won't find a
> better case for TR than this, except if you add complex numbers.

I don't think that this is accurate, Sam.

This is the difference I see and it is more in line with what I would
expect given how I think TR inserts unsafe calls, etc.

[robby at gaoping] ~/git/plt/src/build$ racket ~/tmp-tr.rkt
cpu time: 187 real time: 221 gc time: 6
[robby at gaoping] ~/git/plt/src/build$ racket ~/tmp.rkt
cpu time: 301 real time: 400 gc time: 103
[robby at gaoping] ~/git/plt/src/build$ cat ~/tmp.rkt
#lang racket/base

(define epsilon 1e-7)

(define (my-sqrt y)
  (let loop [(x (/ y 2.0))]
    (let [(error (- y (* x x)))]
      (if (< (abs error) epsilon)
          x
          (loop (+ x (/ error 2 x)))))))

(define (time-and-compare size count)
  (define n (build-list size (lambda (_) (random 10))))
  (collect-garbage) (collect-garbage) (collect-garbage)
  (define l (time (for ([x (in-range 0 count)])
                    (for-each my-sqrt n))))
  (void))

(time-and-compare 100 2000)
[robby at gaoping] ~/git/plt/src/build$ cat ~/tmp-tr.rkt
#lang typed/racket

(define epsilon 1e-7)

(: my-sqrt : Natural -> Real)
(define (my-sqrt y)
  (let loop [(x (/ y 2.0))]
    (let [(error (- y (* x x)))]
      (if (< (abs error) epsilon)
          x
          (loop (+ x (/ error 2 x)))))))

(: time-and-compare : Natural Natural -> Void)
(define (time-and-compare size count)
  (define n (build-list size (lambda (_) (random 10))))
  (collect-garbage) (collect-garbage) (collect-garbage)
  (define l (time (for ([x (in-range 0 count)])
                    (for-each my-sqrt n))))
  (void))

(time-and-compare 100 2000)



Posted on the users mailing list.