[Larceny-users] Performance of List Based Data Structures With ERR5RS Recorcs
Felix Klock
felixluser at pnkfx.org
Sun Sep 14 15:40:43 EDT 2008
Ray-
On Sep 14, 2008, at 11:05 AM, Ray Racine wrote:
> Naively I did not expect this result in the sense of O(1) for vector-
> like vs. O(n) of cons lists.
I think you may have to use larger records/lists before you'll see the
O(1) versus O(n) matter more than the constant factors. (A list of
length 5 is still pretty short.)
> Records are almost 10x slower then cons lists.
I think you may need to take care in what you are comparing: the cost
of accessing fields in a particular data representation, or the cost
of a procedure call versus a primitive operation that executes as
inlined machine code.
Here's a couple more cases I added to your example:
;;; RAYS ORIGINAL CODE
;;; (with one change, replacing the symbol 'lists with the symbol
'lists-ca/dr)
(import (rnrs))
(import (err5rs records syntactic))
(import (primitives time))
(define-record-type rec
#t #t a b c d e)
'records
(time
(let ((r (make-rec 'a 'b 'c 'd 'e)))
(do ((i 10000000 (fx- i 1)))
((fxzero? i)
(rec-e r))
(rec-a r)
(rec-b r)
(rec-c r)
(rec-d r)
(rec-e r)
)))
'lists-ca/dr
(time
(let ((data '(a b c d e)))
(do ((i 10000000 (fx- i 1)))
((fxzero? i)
(cadr (cdddr data)))
(car data)
(cadr data)
(caddr data)
(cadddr data)
(cadr (cdddr data))
)))
;;; FELIXS NEW CODE
'lists-ref
(time
(let ((data '(a b c d e)))
(do ((i 10000000 (fx- i 1)))
((fxzero? i)
(list-ref data 4))
(list-ref data 0)
(list-ref data 1)
(list-ref data 2)
(list-ref data 3)
(list-ref data 4)
)))
'lists-accessors
(define (list-a data) (car data))
(define (list-b data) (cadr data))
(define (list-c data) (caddr data))
(define (list-d data) (cadddr data))
(define (list-e data) (cadr (cdddr data)))
(time
(let ((data '(a b c d e)))
(do ((i 10000000 (fx- i 1)))
((fxzero? i)
(list-ref data 4))
(list-a data)
(list-b data)
(list-c data)
(list-d data)
(list-e data)
)))
;;; END OF CODE
The 'list-accessors code at the end is meant to be the closest match
to the 'records code, since both involve procedure invocations for
"field access"
Here are the results I get when I run this. (I don't have the specs
for the machine immediately available, but for future reference, I'm
doing these experiments on the machine named "artichoke" in the CCIS
lab)
> records
> Words allocated: 0
Words reclaimed: 0
Elapsed time...: 1115 ms (User: 1112 ms; System: 4 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)
e
> lists-ca/dr
> Words allocated: 0
Words reclaimed: 0
Elapsed time...: 141 ms (User: 140 ms; System: 0 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)
e
> lists-ref
> Words allocated: 0
Words reclaimed: 0
Elapsed time...: 1759 ms (User: 1752 ms; System: 4 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)
e
> lists-accessors
>
>
>
>
>
> Words allocated: 0
Words reclaimed: 0
Elapsed time...: 635 ms (User: 636 ms; System: 0 ms)
Elapsed GC time: 0 ms (CPU: 0 in 0 collections.)
e
So from this I conclude:
1. Inlined car/cdr beats field access via function invocation (in all
three cases).
2. Out-of-line car/cdr beats record accessor functions (by about 2x,
not 10x).
3. List-ref is slower than record accessor functions.
A more thorough experiment would also include a comparison with a
representation based directly on vectors. A more thorough analysis
would also include disassembly of the machine code generated for the
different cases above.
I admit that conclusion 2 above is a little surprising. I suspect the
record accessors are paying some fixed cost in checking that the input
is of the correct record type; the corresponding predicates for pairs
are heavily bummed.
-Felix
More information about the Larceny-users
mailing list