Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread D Herring

On 05/04/2011 03:57 PM, Tony Garnock-Jones wrote:

A simple experiment I just performed suggests that a monomorphic
inline cache hit can reduce the time needed for a send in Racket from
350ns to around 60ns, which is a massive win. I've attached the
program I used to measure this, FWIW. (Run it using command-line
Racket, not DrRacket: I got some *very* weird timing artifacts out of
DrRacket during this experiment!)

The question, then, is: how do we implement MICs or PICs using
Racket's macro system? Each send site needs to expand into

- a piece of global state
- a test involving that global state
- a possible update to that global state


You might borrow some ideas from this description of call-site caching 
in SBCL.

http://random-state.net/log/3507261942.html

Later,
Daniel

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Brian Mastenbrook

On 05/01/2011 02:20 AM, D Herring wrote:

Also collect a set of "cool" programs for people to use.  It is easier
for people to understand "this was implemented in Racket" than "Racket's
features might let me make that".  Many people make decisions based on
first impressions.  When I was an undergrad, I preferred "Clean" over
the ML languages largely because the former had a side-scrolling game
demo...  Here's another anecdote.
http://prog21.dadgum.com/97.html


How many other open source languages or libraries make it as easy to 
write native GUI applications on Windows, OS X and X11? I'm having a 
hard time thinking of any. Surely this is an opportunity for some killer 
demo programs.


--
Brian Mastenbrook
br...@mastenbrook.net
http://brian.mastenbrook.net/

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Robby Findler
That button is gone and they are standalone scripts now in
collects\tests\drracket. io.rkt is short, module-language is shortish
and language is long.

Robby

On Wed, May 4, 2011 at 7:18 PM, Ryan Culpepper  wrote:
> On 05/04/2011 04:49 PM, Tony Garnock-Jones wrote:
>>
>> The attached (highly experimental) patch seems to improve the
>> performance of normal sends (in the case of a cache hit) by roughly 100%
>> - 150%. The difference between this mere factor of two improvement and
>> the factor of six-through-ten I was seeing earlier is, I speculate,
>> related to object-ref taking a lot of time.
>>
>> Interestingly, the performance of (send something message) is, with this
>> patch, seemingly roughly en par with the performance of generics
>> captured using generic and invoked using send-generic.
>>
>> I haven't yet tried running a full racket system with this patch
>> applied. I wonder if it makes a difference to the interactive
>> performance of DrRacket?
>
> Robby: What happened to the drracket automated gui tests? I remember there
> used to be an environment variable to enable the button that ran them, but I
> can't find it in the manual or in the source tree.
>
> Ryan
>
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Matthias Felleisen

Racket is the coolest programming language on earth. 
Spend a bit of time with it, and your programs will
grow more beautiful in front of your eyes every day
of your life. 
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Brian Mastenbrook

On 05/04/2011 06:31 PM, Justin Zamora wrote:

On Sun, May 1, 2011 at 3:20 AM, D Herring  wrote:

You might emphasize that Racket is a "new language, borrowing the best parts
of Scheme (and other languages?) and extending it with these features"...


A sentence like that would be a good replacement for the awful,
"Racket is a programming language" currently on the front page of
racket-lang.org   Perhaps something like "Racket is a new language
that borrows the best parts of Scheme, Java, and other languages and
extends them with advanced features such as contracts, types,
user-defined languages, a complete GUI framework and other modern
features."


It's a bit long, and it feels like a list of bullet points. The type of 
person who will read and digest that one-sentence summary isn't the type 
of person who needs a one-sentence summary in the first place. Compare 
and contrast the Python summary linked by the GP:


"Python is a programming language that lets you work more quickly and 
integrate your systems more effectively."


There's no mention of technology (other than that it's a programming 
language). It's all about how Python is intended to be used. The next 
sentence hammers this point home: "You can learn to use Python and see 
almost immediate gains in productivity and lower maintenance costs."


Your suggested Racket summary answers the "What?" question: "What is 
Racket?". The Python summary answers the "Why?" question, as in "Why 
would I want to spend any time reading about this Python thing?". If you 
haven't answered that question sufficiently, nobody will want to read 
the "What?". That's not to say that the answer for Racket needs to be as 
dry and purpose-focused as the Python answer, but it does need to catch 
the person who wanders in from Google and give them a reason to keep 
reading to the bottom of the page.


So, with that in mind, if I know Java or Python, why do I want to spend 
the next 10 minutes of my life reading about Racket - in two sentences 
or less?


--
Brian Mastenbrook
br...@mastenbrook.net
http://brian.mastenbrook.net/

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Ryan Culpepper

On 05/04/2011 04:49 PM, Tony Garnock-Jones wrote:

The attached (highly experimental) patch seems to improve the
performance of normal sends (in the case of a cache hit) by roughly 100%
- 150%. The difference between this mere factor of two improvement and
the factor of six-through-ten I was seeing earlier is, I speculate,
related to object-ref taking a lot of time.

Interestingly, the performance of (send something message) is, with this
patch, seemingly roughly en par with the performance of generics
captured using generic and invoked using send-generic.

I haven't yet tried running a full racket system with this patch
applied. I wonder if it makes a difference to the interactive
performance of DrRacket?


Robby: What happened to the drracket automated gui tests? I remember 
there used to be an environment variable to enable the button that ran 
them, but I can't find it in the manual or in the source tree.


Ryan
_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Shriram Krishnamurthi
Justin is right other than the Java part.  Eli is right with the
amendment of -1 for the suggestion that Java has good parts worth
borrowing. (-:

On Wed, May 4, 2011 at 7:51 PM, Eli Barzilay  wrote:
> 20 minutes ago, Justin Zamora wrote:
>> On Sun, May 1, 2011 at 3:20 AM, D Herring  wrote:
>> > You might emphasize that Racket is a "new language, borrowing the
>> > best parts of Scheme (and other languages?) and extending it with
>> > these features"...
>>
>> A sentence like that would be a good replacement for the awful,
>> "Racket is a programming language" currently on the front page of
>> racket-lang.org Perhaps something like "Racket is a new language
>> that borrows the best parts of Scheme, Java, and other languages and
>> extends them with advanced features such as contracts, types,
>> user-defined languages, a complete GUI framework and other modern
>> features."
>
> -1 for any mention of Java.
>
> --
>          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>                    http://barzilay.org/                   Maze is Life!
> _
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/dev
>

_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Eli Barzilay
20 minutes ago, Justin Zamora wrote:
> On Sun, May 1, 2011 at 3:20 AM, D Herring  wrote:
> > You might emphasize that Racket is a "new language, borrowing the
> > best parts of Scheme (and other languages?) and extending it with
> > these features"...
> 
> A sentence like that would be a good replacement for the awful,
> "Racket is a programming language" currently on the front page of
> racket-lang.org Perhaps something like "Racket is a new language
> that borrows the best parts of Scheme, Java, and other languages and
> extends them with advanced features such as contracts, types,
> user-defined languages, a complete GUI framework and other modern
> features."

-1 for any mention of Java.

-- 
  ((lambda (x) (x x)) (lambda (x) (x x)))  Eli Barzilay:
http://barzilay.org/   Maze is Life!
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread Justin Zamora
On Sun, May 1, 2011 at 3:20 AM, D Herring  wrote:
> You might emphasize that Racket is a "new language, borrowing the best parts
> of Scheme (and other languages?) and extending it with these features"...

A sentence like that would be a good replacement for the awful,
"Racket is a programming language" currently on the front page of
racket-lang.org   Perhaps something like "Racket is a new language
that borrows the best parts of Scheme, Java, and other languages and
extends them with advanced features such as contracts, types,
user-defined languages, a complete GUI framework and other modern
features."

Justin
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Matthias Felleisen

Wow. Why didn't I think of asking for this before :-) 


On May 4, 2011, at 7:11 PM, Ryan Culpepper wrote:

> On 05/04/2011 01:57 PM, Tony Garnock-Jones wrote:
>> On 2011-05-04 12:04 PM, Matthias Felleisen wrote:
>>> I still believe that the Java implementation (just under 1s without
>>> their 'Google' contract) benefits from typed dispatches.
>> 
>> Maybe it does, but it's almost certain that it is benefiting from inline
>> caching at send sites (i.e. dynamic type information) much more than it
>> will be benefiting from static type information.
>> 
>> A quick-and-dirty comparison of raw send performance on my Mac:
>> 
>> Language Virtual machine Nanoseconds per send
>> 
>> Java Hotspot 64-bit 1.6.0_24 1.4
>> Smalltalk Cog r2382 21
>> Smalltalk SqueakVM 4.2.4beta1U 122
>> Racket Racket v5.1 ~350
>> 
>> Note that Cog is a JITting VM and SqueakVM is a plain (but very well
>> optimised) interpreter. Both Cog and SqueakVM use a couple of levels of
>> method lookup cache.
>> 
>> A simple experiment I just performed suggests that a monomorphic inline
>> cache hit can reduce the time needed for a send in Racket from 350ns to
>> around 60ns, which is a massive win. I've attached the program I used to
>> measure this, FWIW. (Run it using command-line Racket, not DrRacket: I
>> got some *very* weird timing artifacts out of DrRacket during this
>> experiment!)
>> 
>> The question, then, is: how do we implement MICs or PICs using Racket's
>> macro system? Each send site needs to expand into
>> 
>> - a piece of global state
>> - a test involving that global state
>> - a possible update to that global state
>> 
>> Hypothesising some kind of (let-static) form that introduces a
>> lexically-scoped piece of global state,
> 
> Here's 'let-static':
> 
>  (define-syntax (let-static stx)
>(syntax-case stx ()
>  [(let-static ([var rhs] ...) . body)
>   (with-syntax ([(gvar ...)
>  (syntax-local-lift-values-expression
>   (length (syntax->list #'(var ...)))
>   #'(values rhs ...))])
> #'(let-syntax ([var (make-rename-transformer #'gvar)] ...)
> . body))]))
> 
> > this kind of thing might Just
>> Work to provide a speedup of almost six-fold on almost-monomorphic
>> send-heavy code:
> 
>> (define-syntax cached-send
>>  (syntax-rules ()
>>((_ obj msg arg ...)
>> (let-static ((bc (box #f))
>>  (bm (box #f)))
>>   (let* ((tmp obj)
>>  (cls (object-ref tmp)))
>> (if (eq? (unbox bc) cls)
>> ((unbox bm) tmp arg ...)
>> (let-values (((method _)
>>   (find-method/who 'send tmp 'msg)))
>>   (set-box! bc cls)
>>   (set-box! bm method)
>>   (method tmp arg ...
> 
> That code has a space-safety problem: the caches might keep around classes 
> that should be garbage collected. It also has a race condition: there's a 
> period of time when the class cache has been updated but the method cache 
> hasn't.
> 
> The safe-for-space issue can be fixed by using weak boxes. The race condition 
> could be fixed by using one instead of two... but there's no structure that 
> combines a class and a particular method implementation that's strongly held 
> elsewhere. Creating a new pair for the weak box to hold works, but it means 
> that every GC is likely to flush the cache, but maybe that's okay. It also 
> means that every cache miss triggers heap allocation, but I don't know any 
> way around that.
> 
> I've attached an updated benchmark script. Still looks like a win on speed, 
> but slightly less than before.
> 
> Ryan
> _
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/dev


_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Ryan Culpepper

On 05/04/2011 01:57 PM, Tony Garnock-Jones wrote:

On 2011-05-04 12:04 PM, Matthias Felleisen wrote:

I still believe that the Java implementation (just under 1s without
their 'Google' contract) benefits from typed dispatches.


Maybe it does, but it's almost certain that it is benefiting from inline
caching at send sites (i.e. dynamic type information) much more than it
will be benefiting from static type information.

A quick-and-dirty comparison of raw send performance on my Mac:

Language Virtual machine Nanoseconds per send

Java Hotspot 64-bit 1.6.0_24 1.4
Smalltalk Cog r2382 21
Smalltalk SqueakVM 4.2.4beta1U 122
Racket Racket v5.1 ~350

Note that Cog is a JITting VM and SqueakVM is a plain (but very well
optimised) interpreter. Both Cog and SqueakVM use a couple of levels of
method lookup cache.

A simple experiment I just performed suggests that a monomorphic inline
cache hit can reduce the time needed for a send in Racket from 350ns to
around 60ns, which is a massive win. I've attached the program I used to
measure this, FWIW. (Run it using command-line Racket, not DrRacket: I
got some *very* weird timing artifacts out of DrRacket during this
experiment!)

The question, then, is: how do we implement MICs or PICs using Racket's
macro system? Each send site needs to expand into

- a piece of global state
- a test involving that global state
- a possible update to that global state

Hypothesising some kind of (let-static) form that introduces a
lexically-scoped piece of global state,


Here's 'let-static':

  (define-syntax (let-static stx)
(syntax-case stx ()
  [(let-static ([var rhs] ...) . body)
   (with-syntax ([(gvar ...)
  (syntax-local-lift-values-expression
   (length (syntax->list #'(var ...)))
   #'(values rhs ...))])
 #'(let-syntax ([var (make-rename-transformer #'gvar)] ...)
 . body))]))

> this kind of thing might Just

Work to provide a speedup of almost six-fold on almost-monomorphic
send-heavy code:



(define-syntax cached-send
  (syntax-rules ()
((_ obj msg arg ...)
 (let-static ((bc (box #f))
  (bm (box #f)))
   (let* ((tmp obj)
  (cls (object-ref tmp)))
 (if (eq? (unbox bc) cls)
 ((unbox bm) tmp arg ...)
 (let-values (((method _)
   (find-method/who 'send tmp 'msg)))
   (set-box! bc cls)
   (set-box! bm method)
   (method tmp arg ...


That code has a space-safety problem: the caches might keep around 
classes that should be garbage collected. It also has a race condition: 
there's a period of time when the class cache has been updated but the 
method cache hasn't.


The safe-for-space issue can be fixed by using weak boxes. The race 
condition could be fixed by using one instead of two... but there's no 
structure that combines a class and a particular method implementation 
that's strongly held elsewhere. Creating a new pair for the weak box to 
hold works, but it means that every GC is likely to flush the cache, but 
maybe that's okay. It also means that every cache miss triggers heap 
allocation, but I don't know any way around that.


I've attached an updated benchmark script. Still looks like a win on 
speed, but slightly less than before.


Ryan
#lang racket
(require racket/private/class-internal)

(define-syntax (let-static stx)
  (syntax-case stx ()
[(let-static ([var rhs] ...) . body)
 (with-syntax ([(gvar ...)
(syntax-local-lift-values-expression
 (length (syntax->list #'(var ...)))
 #'(values rhs ...))])
   #'(let-syntax ([var (make-rename-transformer #'gvar)] ...)
   . body))]))

;; An ordinary Racket class.
(define a%
  (class* object% ()
(super-new)
(define/public (op x) (+ x 1
;;  Cached versions of send 

;; (Real version should base cache on class, not object.)

;; send/cache0
;; Uses 2 vars.
;; Problem: not safe for space!
;; Problem: race condition in 2 set!s.
(define-syntax send/cache0
  (syntax-rules ()
[(_ obj-expr msg arg ...)
 (let-static ([*memo-class* #f]
  [*memo-method* #f])
   (let ([obj obj-expr])
 (let ([f (if (eq? obj *memo-class*)
  *memo-method*
  (let-values ([(method _obj)
(find-method/who 'send obj 'msg)])
(set! *memo-class* obj)
(set! *memo-method* method)
method))])
   (f obj arg ...]))

;; send/cache1
;; Uses 2 weak-boxes to be safe for space.
;; Problem: race condition in 2 set!s.
(define-syntax send/cache1
  (syntax-rules ()
((_ obj-expr msg arg ...)
 (let-static ([*memo-class* (make-weak-box #f)]
  [*memo-method* (make-weak-box #f)])
   (let* ([obj obj-expr]
 

Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Tony Garnock-Jones

On 2011-05-04 6:54 PM, Asumu Takikawa wrote:

Wow, impressive! I've been benchmarking with the DrRacket interactive
tests already for contracts, so I can run my test driver and get some
numbers for that.


That'd be great. I mean, it'll probably just break, but if it doesn't... 
it'd be interesting :-)


Tony
_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Asumu Takikawa
On 2011-05-04 18:49:13 -0400, Tony Garnock-Jones wrote:
> The attached (highly experimental) patch seems to improve the
> performance of normal sends (in the case of a cache hit) by roughly
> 100% - 150%. The difference between this mere factor of two
> improvement and the factor of six-through-ten I was seeing earlier
> is, I speculate, related to object-ref taking a lot of time.
> 
> Interestingly, the performance of (send something message) is, with
> this patch, seemingly roughly en par with the performance of
> generics captured using generic and invoked using send-generic.
> 
> I haven't yet tried running a full racket system with this patch
> applied. I wonder if it makes a difference to the interactive
> performance of DrRacket?

Wow, impressive! I've been benchmarking with the DrRacket interactive
tests already for contracts, so I can run my test driver and get some
numbers for that.

Cheers,
Asumu
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Tony Garnock-Jones
The attached (highly experimental) patch seems to improve the 
performance of normal sends (in the case of a cache hit) by roughly 100% 
- 150%. The difference between this mere factor of two improvement and 
the factor of six-through-ten I was seeing earlier is, I speculate, 
related to object-ref taking a lot of time.


Interestingly, the performance of (send something message) is, with this 
patch, seemingly roughly en par with the performance of generics 
captured using generic and invoked using send-generic.


I haven't yet tried running a full racket system with this patch 
applied. I wonder if it makes a difference to the interactive 
performance of DrRacket?


Major weaknesses of the approach:

 - overhead on cache miss is unknown
 - not safe-for-space yet (weak boxes are immutable)

The approach should generalize easily to polymorphic inline caches.

Regards,
  Tony
diff --git a/collects/racket/private/class-internal.rkt 
b/collects/racket/private/class-internal.rkt
index d00ef10..0a96cba 100644
--- a/collects/racket/private/class-internal.rkt
+++ b/collects/racket/private/class-internal.rkt
@@ -3734,19 +3734,30 @@
   (let ()
 
 (define (do-method traced? stx form obj name args rest-arg?)
-  (with-syntax ([(sym method receiver)
- (generate-temporaries (syntax (1 2 3)))])
+  (with-syntax ([(sym in-object in-class state method receiver)
+ (generate-temporaries (syntax (1 2 3 4 5 6)))]
+   [*cached-state*
+(syntax-local-lift-expression
+ (syntax (cons #f #f)))])
 (quasisyntax/loc stx
   (let*-values ([(sym) (quasiquote (unsyntax (localize name)))]
-[(method receiver)
- (find-method/who '(unsyntax form)
-  (unsyntax obj)
-  sym)])
+   [(in-object) (unsyntax obj)]
+   [(in-class) (and (object? in-object) (object-ref 
in-object))]
+   [(state) *cached-state*]
+[(method)
+(if (and in-class (eq? (car state) in-class))
+(cdr state)
+(let-values ([(m r)
+  (find-method/who '(unsyntax form)
+   in-object
+   sym)])
+  (set! *cached-state* (cons in-class m))
+  m))])
 (unsyntax
  (make-method-call
   traced?
   stx
-  (syntax/loc stx receiver)
+  (syntax/loc stx in-object)
   (syntax/loc stx method)
   (syntax/loc stx sym)
   args
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev

Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Jos Koot
 

> -Original Message-
> From: dev-boun...@racket-lang.org 
> [mailto:dev-boun...@racket-lang.org] On Behalf Of Matthias Felleisen
> Sent: 04 May 2011 22:58
> To: Tony Garnock-Jones; D Herring
> Cc: dev List
> Subject: Re: [racket-dev] Inline caching (was Re: my '312' 
> this semester,how we compare to others)
> 
> 
> As I was reading a paper, I encountered the word 'cache' and 
> remembered that I had wanted to implement a caching version 
> of the central method in my central data structure. That took 
> me about 10 minutes, and I now have good times for the game: 
> 
> with contracts: 1.8s per game 
> without ctrcts: 1.2s per game 
> 
> I am now within 20% of the fastest Java implementation in my 
> class. That's good. 
> 
> -- Matthias
> 
> p.s. Okay, I'll say it: algorithms matter, too. 


That to me seems most important.
Of course inplementation of an algortithm requires wisdom too:

Is cashing of data faster than recomputing them?
How do we deal with shortage of RAM?
How do we optimize software? (nowadays surely not by hand)
Do software devellopers inspire hardware designers, or may/should it be the
orher way around?
There is a tendency to separate programmers from the hardware equipment they
are using. Is this wise?

I think hardware designers must understand programmers and vice versa.
Most important, both parties must understand their customers.

mho, Jos

> _
>   For list-related administrative tasks:
>   http://lists.racket-lang.org/listinfo/dev

_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Matthias Felleisen

As I was reading a paper, I encountered the word 'cache' and remembered that I 
had wanted to implement a caching version of the central method in my central 
data structure. That took me about 10 minutes, and I now have good times for 
the game: 

with contracts: 1.8s per game 
without ctrcts: 1.2s per game 

I am now within 20% of the fastest Java implementation in my class. That's 
good. 

-- Matthias

p.s. Okay, I'll say it: algorithms matter, too. 
_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Tony Garnock-Jones

On 2011-05-04 3:57 PM, Tony Garnock-Jones wrote:

reduce the time needed for a send in Racket from 350ns to around 60ns


That was on a fancy-pants Macbook Air 1.6GHz Core 2 Duo or whatever.

On one of the stock Pentium 4 2.8GHz 32-bit Linux machines in the lab, 
running Racket v5.1.1, using the same sketch-of-an-inline-cache attached 
to my previous message, I see send times drop by a factor of about 10, 
from ~260ns to ~26ns.


Tony
_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


[racket-dev] Inline caching (was Re: my '312' this semester, how we compare to others)

2011-05-04 Thread Tony Garnock-Jones

On 2011-05-04 12:04 PM, Matthias Felleisen wrote:

I still believe that the Java implementation (just under 1s without
their 'Google' contract) benefits from typed dispatches.


Maybe it does, but it's almost certain that it is benefiting from inline 
caching at send sites (i.e. dynamic type information) much more than it 
will be benefiting from static type information.


A quick-and-dirty comparison of raw send performance on my Mac:

  Language Virtual machine  Nanoseconds per send
 
  Java Hotspot 64-bit 1.6.0_24  1.4
  SmalltalkCog r2382   21
  SmalltalkSqueakVM 4.2.4beta1U   122
  Racket   Racket v5.1   ~350

Note that Cog is a JITting VM and SqueakVM is a plain (but very well 
optimised) interpreter. Both Cog and SqueakVM use a couple of levels of 
method lookup cache.


A simple experiment I just performed suggests that a monomorphic inline 
cache hit can reduce the time needed for a send in Racket from 350ns to 
around 60ns, which is a massive win. I've attached the program I used to 
measure this, FWIW. (Run it using command-line Racket, not DrRacket: I 
got some *very* weird timing artifacts out of DrRacket during this 
experiment!)


The question, then, is: how do we implement MICs or PICs using Racket's 
macro system? Each send site needs to expand into


 - a piece of global state
 - a test involving that global state
 - a possible update to that global state

Hypothesising some kind of (let-static) form that introduces a 
lexically-scoped piece of global state, this kind of thing might Just 
Work to provide a speedup of almost six-fold on almost-monomorphic 
send-heavy code:


(define-syntax cached-send
  (syntax-rules ()
((_ obj msg arg ...)
 (let-static ((bc (box #f))
  (bm (box #f)))
   (let* ((tmp obj)
  (cls (object-ref tmp)))
 (if (eq? (unbox bc) cls)
 ((unbox bm) tmp arg ...)
 (let-values (((method _)
   (find-method/who 'send tmp 'msg)))
   (set-box! bc cls)
   (set-box! bm method)
   (method tmp arg ...

Regards,
  Tony
#lang racket
(require racket/private/class-internal)

;; An ordinary Racket class.
(define a%
  (class* object% ()
(super-new)
(define/public (op x) (+ x 1

;; Representation of a trivial vtable.
(struct ob (vt state) #:transparent)

;; A simple vtable providing a single method named "op".
(define (b%-vt selector)
  (case selector
((op) (lambda (self x) (+ x 2)))
(else (error 'dnu

;; A simple class, using b%-vt as its behaviour.
(define (b%)
  (ob b%-vt 'no-state))

;; An uncached send to a struct ob.
(define-syntax unmemo-send
  (syntax-rules ()
((_ obj msg arg ...)
 (let ((tmp obj))
   (((ob-vt tmp) 'msg) tmp arg ...)

;; A quasi-cached send to a struct ob.
;;
;; A real cache would have per-send-site state rather than a single
;; (!) global variable.
(define *memo-class* #f)
(define *memo-method* #f)
(define-syntax memo-send
  (syntax-rules ()
((_ obj msg arg ...)
 (let* ((tmp obj)
(cls (ob-vt tmp)))
   (if (eq? *memo-class* cls)
   (*memo-method* tmp arg ...)
   (let ((method (cls 'msg)))
 (set! *memo-class* cls)
 (set! *memo-method* method)
 (method tmp arg ...)))

;; Test objects.
(define a0 (new a%))
(define b0 (b%))

;; Syntax: (measure-ns exp)
;;
;; Expands to an expression that repeats "exp" NREPEATS times,
;; measuring the elapsed time, and returns the number of nanoseconds
;; of CPU time used *per iteration*, excluding any GC time.
(define NREPEATS 500)
(define-syntax measure-ns
  (syntax-rules ()
((_ exp)
 (call-with-values (lambda ()
 (pretty-print `(measuring exp))
 (time-apply (lambda ()
   (do ((i 0 (+ i 1)))
 ((= i NREPEATS))
 exp))
 '()))
   (lambda (results cpu real gc)
 (/ (* 10.0 (/ (- cpu gc) 1000.0))
NREPEATS))

;; Main program.

;; Measure the time for a null measure-ns loop first, then measure the
;; operations of interest, subtracting the null-time overhead
;; measurement from each to get an estimate of the time taken for the
;; interesting operation.

(let ((null-time (measure-ns 123)))
  (define (report-on t)
(let ((name (first t))
  (ns/op (second t)))
  (write (list name (- ns/op null-time)))
  (newline)))
  (for-each report-on
`(
  ;; Report on the loop overhead for sanity checking.
  (constant ,null-time)

  ;; How long does a plain Scheme addition operation take?
  (simple-add
  

Re: [racket-dev] git error help?

2011-05-04 Thread Robby Findler
Thanks! (I don't know why, but I'm just getting this message now.)

Robby

On Sun, May 1, 2011 at 2:04 AM, D Herring  wrote:
> On 04/25/2011 10:32 AM, Robby Findler wrote:
>>
>> Anyone recognize this? (git up is git pull --ff-only --stat --all)
>>
>> C:\Users\Administrator\git\exp\plt>git up
>> Fetching origin
>> error: unable to resolve reference refs/remotes/origin/master: No error
>>  From git:plt
>>  ! [new branch]      master     ->  origin/master  (unable to update local
>> ref)
>> error: Could not fetch origin
>
> For the future, try 'git fetch -v origin'.  A pull is a fetch plus a merge,
> this error indicates the fetch was failing, and the verbose fetch might give
> more diagnostics.
>
> The following commands show the settings used by fetch.
> # git config remote.origin.url
> # git config remote.origin.fetch
>
> Maybe one of them was broken?
>
> - Daniel
>
> _
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/dev
>

_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev

Re: [racket-dev] my '312' this semester, how we compare to others

2011-05-04 Thread Matthias Felleisen

On May 1, 2011, at 2:58 AM, D Herring wrote:

> On 04/21/2011 01:07 PM, Matthias Felleisen wrote:
>> -B- When it comes to raw computational performance (ignore loading Racket, 
>> start from REPL and run a single game -- 10 seconds), my implementation is 
>> faster than Python (but barely) and one of the Java implementations. But one 
>> Java implementation is 10x faster. My hunch is that our OO system is 
>> significantly slower than Java's because we lack types to reduce dispatch 
>> overhead. Then again I might be wrong. -- Another possibility is that my 
>> extremely heavy use of our wonderful (!) contracts may impose a large 
>> overhead. I use mostly ->i and ->m.
> 
> I'd be curious what your timings are with the contract checking disabled.

I have recently reported the revised timings to a small list of core 
Racketeers, but here is the upshot: 

1. I found a serious performance bug in one of two central methods during a 
final code revision. 

2. Now the code with contracts runs a game in just over 3s. 

3. Disabling contracts lowers this to just over 2s. 
(These timings are averages of 30 games.)

4. The Racket implementation is now the second fastest implementation in the 
bunch. I still believe that the Java implementation (just under 1s without 
their 'Google' contract) benefits from typed dispatches. 
(There are no significant numeric computations in this game to affect 
the run time.) 

-- Matthias


_
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] racket vs. scheme vs. clojure (as it appears to others)

2011-05-04 Thread D Herring

On 04/29/2011 12:10 PM, Matthias Felleisen wrote:



On Apr 29, 2011, at 11:31 AM, Neil Van Dyke wrote:


  "Scheme" is usually a liability when someone used it in school years ago 
(other than with HtDP).


Sad.


but true.  Exacerbated by lecturers who refused to keep up with the 
world around them, thus projecting their failings onto their language 
of choice.  It took me several years to forget and some very 
"made-for-lisp" coding projects at work before I gave lisp a second 
try.  The PLT logo still messes with my subconscious.


You might emphasize that Racket is a "new language, borrowing the best 
parts of Scheme (and other languages?) and extending it with these 
features"...


Put a big "What is Racket?" link on the Racket home page.  Fill it 
with features and promise.  (c.f. http://qt.nokia.com/ or 
http://python.org/)


Also collect a set of "cool" programs for people to use.  It is easier 
for people to understand "this was implemented in Racket" than 
"Racket's features might let me make that".  Many people make 
decisions based on first impressions.  When I was an undergrad, I 
preferred "Clean" over the ML languages largely because the former had 
a side-scrolling game demo...  Here's another anecdote.

http://prog21.dadgum.com/97.html

- Daniel

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] git error help?

2011-05-04 Thread D Herring

On 04/25/2011 10:32 AM, Robby Findler wrote:

Anyone recognize this? (git up is git pull --ff-only --stat --all)

C:\Users\Administrator\git\exp\plt>git up
Fetching origin
error: unable to resolve reference refs/remotes/origin/master: No error
 From git:plt
  ! [new branch]  master ->  origin/master  (unable to update local ref)
error: Could not fetch origin


For the future, try 'git fetch -v origin'.  A pull is a fetch plus a 
merge, this error indicates the fetch was failing, and the verbose 
fetch might give more diagnostics.


The following commands show the settings used by fetch.
# git config remote.origin.url
# git config remote.origin.fetch

Maybe one of them was broken?

- Daniel

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev


Re: [racket-dev] my '312' this semester, how we compare to others

2011-05-04 Thread D Herring

On 04/21/2011 01:07 PM, Matthias Felleisen wrote:

-B- When it comes to raw computational performance (ignore loading Racket, start from 
REPL and run a single game -- 10 seconds), my implementation is faster than Python 
(but barely) and one of the Java implementations. But one Java implementation is 10x 
faster. My hunch is that our OO system is significantly slower than Java's because we 
lack types to reduce dispatch overhead. Then again I might be wrong. -- Another 
possibility is that my extremely heavy use of our wonderful (!) contracts may impose 
a large overhead. I use mostly ->i and ->m.


I'd be curious what your timings are with the contract checking disabled.

As for lacking types, types are only useful for primitive 
optimizations; partial evaluation and code profiling and "inlining" 
sequential dispatches have the potential to outperform C++ vtables, 
etc.  C/C++ must rely on link-time optimization frameworks and Java is 
hampered by doing everything at runtime...  I think this is a big area 
of opportunity for lisp systems to regain the performance lead.


As to the wider issue, "glue languages" will probably win in the long 
run; there are huge masses of legacy code, but everybody wants to use 
a newer language.  If you could fairly seamlessly employ a C++ or Java 
library in lisp...  C is dominant largely because it has a simple 
calling convention.  Lisp systems do not...  They tend to be 
frameworks, not externally extensible tools.


- Daniel

_
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/dev