[racket] Everything type-checks; on to benchmarking and optimization

From: Vincent St-Amour (stamourv at ccs.neu.edu)
Date: Fri Feb 28 11:23:58 EST 2014

At Fri, 28 Feb 2014 10:50:11 -0500,
Stephen Bloch wrote:
> 
> On Feb 28, 2014, at 10:34 AM, Vincent St-Amour <stamourv at ccs.neu.edu> wrote:
> 
> > This code is probably the problem:
> > 
> >    (require/typed racket/unsafe/ops
> >                   [(unsafe-fx+ index+) [Index Index -> Index]]
> >                   [unsafe-fx+    [Fixnum Fixnum -> Fixnum]]
> >                   [unsafe-fx- (Fixnum Fixnum -> Fixnum)]
> >                   [unsafe-fl+ (Flonum Flonum -> Flonum)]
> >                   [unsafe-fl- (Flonum Flonum -> Flonum)]
> >                   [unsafe-fl* (Flonum Flonum -> Flonum)]
> >                   )
> > 
> > TR already provides types for these functions, so you can use:
> > 
> >    (require racket/unsafe/ops)
> > 
> > `require/typed' adds contracts to its imports (for safe typed-untyped
> > interop), which add a significant cost (85% of the running time,
> > according to the contract profiler).
> 
> Yike!  Thanks; I never would have thought of that.
> 
> There’s probably something in the documentation about “require/typed”
> as a source of inefficiency, but for whatever reason I didn’t stumble
> upon it.

The "typed-untyped interaction" section of the TR guide does mention the
overhead of contracts. I'll add mentions elsewhere in the docs (probably
in the caveats and optimization sections).

> > Removing the `require/typed' (except for `index+') brings the running
> > time (of the portion you were profiling) down from 22s to 15s. Replacing
> > the `index+'s with generic `+' and `assert's (to enforce `Index'
> > results) brings the running time down to 2.5s.
> 
> Generic ‘+’, not ‘unsafe-fx+’?

In this case, Typed Racket optimized it automatically based on the type
information, as confirmed by optimization coach.

> Should I be using racket/unsafe/ops at all?

I would recommend first seeing whether TR already optimizes operations
for you. If it doesn't, you can try adjusting the types. If that doesn't
work, then unsafe operations are a good option. I tend to use them as a
last resort.

Unsafe fixnum operations, specifically, are not usually a significant
improvement over generic arithmetic, because the fixnum case is already
on the fast path of generic operations, and fixnums are not boxed
(unlike flonums).

Vincent

Posted on the users mailing list.