[plt-scheme] ->d Performance
Yeah, that's pretty bad. Below is a smaller example showing that there
about a 16x slowdown for using ->d as compared to ->, even without
doing anything special. And if you change the integer? into (and/c
number? integer?) in the ->d contract, the slowdown is 35x. I did
spent a fair amount of time trying to make -> go fast, but I just
haven't had time to do the same for ->d.
#lang scheme/load
(module m scheme
(provide/contract
[f (-> integer? integer? integer?)]
[g (->d ([x integer?]
[y integer?])
()
[r integer?])])
(define (f x y) x)
(define (g x y) x))
(module n scheme
(require 'm)
(define (run f)
(time
(let loop ([i 10000])
(unless (zero? i)
(f 1 2) (f 3 4) (f 5 6) (f 7 8) (f 9 10)
(loop (- i 1))))))
(run f)
(run g))
(require 'n)
On Sat, Apr 11, 2009 at 3:29 PM, Doug Williams
<m.douglas.williams at gmail.com> wrote:
> Here is a graphical example where you can see the difference in speed.
>
> The life-bitblt-slower.ss requires matrix-slower.ss (with ->d and no bounds
> checking in the body of the code) and is really slow.
>
> The life-bitblt-faster.ss requires matrix-faster.ss (with -> and bounds
> checking in the body of the code) and performs okay.
>
> Other than the contract and the corresponding presence or ansence of bounds
> checking (to give the same functionality), the code is identical. [The only
> difference between life-bitblt-slower.ss and life-bitblt-faster.ss is the
> require statement.]
>
> The life-bitblt-vector.ss version does the matrix abstraction internally
> (using a vector) and doesn't use any external module (or contracts) at all.
> It is by far the fastest, but it's kind of an apples and oranges comparison
> with the others. I'm not sure how much of the speedup is due to the matrix
> abstraction into a module or the contracts.
>
> They all do better compiled. But it interesting to see the speed difference.
>
> Note that the code used the science and animated-canvas collections from
> PLaneT and will download them the first time any of them are run, which
> takes some time.
>
> Doug
>
> On Sat, Apr 11, 2009 at 1:55 PM, Robby Findler <robby at eecs.northwestern.edu>
> wrote:
>>
>> ->d actually evaluates the expressions (and/c
>> exact-nonnegative-integer? (</c (matrix-rows matrix))) each time you
>> call the function, and that evaluation involves building up a contract
>> combinator (and doing various error checking) before actually checking
>> the contract. That's where the extra overhead comes from. In
>> comparison with the -> contract, all of that work is done once, before
>> the contract is even attached to the value. I have experimented with
>> various optimizations to avoid this work, but there is a lot to do to
>> make that happen.
>>
>> Robby
>>
>> On Sat, Apr 11, 2009 at 2:51 PM, Doug Williams
>> <m.douglas.williams at gmail.com> wrote:
>> > Yes, the -> is fine. And, so is doing the same bounds check in my own
>> > procedure. I was surprised that the ->d was so much slower. I use
>> > contracts
>> > regularly and was trying to expand my usage of them.
>> >
>> > On Sat, Apr 11, 2009 at 12:46 PM, Robby Findler
>> > <robby at eecs.northwestern.edu> wrote:
>> >>
>> >> ->d is definitely substantially slower than the other because the
>> >> wrappers are more complex. Are you finding the performance overhead of
>> >> the ordinary -> acceptable?
>> >>
>> >> Robby
>> >>
>> >> On Sat, Apr 11, 2009 at 1:17 PM, Doug Williams
>> >> <m.douglas.williams at gmail.com> wrote:
>> >> > I would like to use ->d to impose a precondition for a function. For
>> >> > example:
>> >> >
>> >> > (matrix-ref
>> >> > (->d ((matrix matrix?)
>> >> > (i (and/c exact-nonnegative-integer? (</c (matrix-rows
>> >> > matrix))))
>> >> > (j (and/c exact-nonnegative-integer? (</c (matrix-cols
>> >> > matrix)))))
>> >> > ()
>> >> > (result any/c)))
>> >> >
>> >> > or
>> >> >
>> >> > (matrix-ref
>> >> > (->d ((matrix matrix?)
>> >> > (i exact-nonnegative-integer?)
>> >> > (j exact-nonnegative-integer?))
>> >> > ()
>> >> > #:pre-cond (and (< i (matrix-rows matrix))
>> >> > (< j (matrix-cols matrix)))
>> >> > (result any/c)))
>> >> >
>> >> > instead of just
>> >> >
>> >> > (matrix-ref
>> >> > (-> matrix? exact-nonnegative-integer? exact-nonnegative-integer?
>> >> > any/c))
>> >> >
>> >> > The first two do work, but are really, really slow.
>> >> >
>> >> > I like having the bounds check in the contract (as opposed to bounds
>> >> > check
>> >> > in the matrix-ref code, but can't accept the performance hit. Any
>> >> > ideas?
>> >> >
>> >> > Doug
>> >> >
>> >> >
>> >> > _________________________________________________
>> >> > For list-related administrative tasks:
>> >> > http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>> >> >
>> >> >
>> >
>> >
>
>