From fd96a129f322eadde72e3883b5d4fdbe20a3cedc Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 12 May 2006 00:03:40 +0000 Subject: [PATCH] Finished with C-ing the code, it's now 2.5 times faster than it was, and spending only 7% of the GC time it used to spend. svn: r2915 --- collects/mzlib/md5.ss | 175 +++++++++++++++++++++++++++--------------- 1 file changed, 114 insertions(+), 61 deletions(-) diff --git a/collects/mzlib/md5.ss b/collects/mzlib/md5.ss index a7b875116e..b936959251 100644 --- a/collects/mzlib/md5.ss +++ b/collects/mzlib/md5.ss @@ -93,63 +93,69 @@ ;; performance. ;; (word c) turns into a quoted pair '(hi . lo) if c is a literal number. + ;; can create a new word, compute one at compile-time etc (define-syntax (word stx) (syntax-case stx () + ;; normal version + [(word #:new c) + #'(let ([n c]) + (if (<= 0 n 4294967296) + (cons (quotient n 65536) (remainder n 65536)) + (error 'word "out of range: ~e" n)))] + ;; to use when the number is known to be in range + [(word #:safe #:new c) #'(word #:new #:safe c)] + [(word #:new #:safe c) + #'(let ([n c]) (cons (quotient n 65536) (remainder n 65536)))] + ;; default form: compute at compile-time if possible [(word c) (let ([n (syntax-e #'c)]) (if (integer? n) - (datum->syntax-object - #'c `(quote ,(cons (quotient n 65536) (remainder n 65536))) #'c) - #'(let ([n c]) - (if (<= 0 n 4294967296) - (cons (quotient n 65536) (remainder n 65536)) - (error 'word "out of range: ~e" n)))))])) + (if (<= 0 n 4294967295) + (datum->syntax-object + #'c `(quote ,(cons (quotient n 65536) (remainder n 65536))) #'c) + (raise-syntax-error #f "constant number out of range" stx)) + #'(word #:new c)))])) - (define (word+ a b) + ;; destructive operations to save on consing + + ;; destructive cons + (define (cons! p x y) + (set-car! p x) + (set-cdr! p y)) + + ;; a := b + (define (word=! a b) + (cons! a (car b) (cdr b))) + + ;; a := a + b + (define (word+=! a b) (let ([t1 (+ (car a) (car b))] [t2 (+ (cdr a) (cdr b))]) - (cons (bitwise-and (+ t1 (arithmetic-shift t2 -16)) 65535) - (bitwise-and t2 65535)))) + (set-car! a (bitwise-and (+ t1 (arithmetic-shift t2 -16)) 65535)) + (set-cdr! a (bitwise-and t2 65535)) + a)) - (define (word-or a b) - (cons (bitwise-ior (car a) (car b)) - (bitwise-ior (cdr a) (cdr b)))) - - (define (word-not a) - (cons (bitwise-and (bitwise-not (car a)) 65535) - (bitwise-and (bitwise-not (cdr a)) 65535))) - - (define (word-xor a b) - (cons (bitwise-xor (car a) (car b)) - (bitwise-xor (cdr a) (cdr b)))) - (define (word-xor3 a b c) - (cons (bitwise-xor (car a) (car b) (car c)) - (bitwise-xor (cdr a) (cdr b) (cdr c)))) - - (define (word-and a b) - (cons (bitwise-and (car a) (car b)) - (bitwise-and (cdr a) (cdr b)))) - - (define word<<< + (define word<<bytesl : word -> (list byte byte byte byte), little endian! (define (word->bytesl w) @@ -277,23 +283,36 @@ (vector (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0) (cons 0 0))) - (let loop ([A (word #x67452301)] - [B (word #xefcdab89)] - [C (word #x98badcfe)] - [D (word #x10325476)] - [a-port a-port] - [done 0]) + (define A (word #:new #:safe #x67452301)) + (define B (word #:new #:safe #xefcdab89)) + (define C (word #:new #:safe #x98badcfe)) + (define D (word #:new #:safe #x10325476)) + (define AA (cons 0 0)) + (define BB (cons 0 0)) + (define CC (cons 0 0)) + (define DD (cons 0 0)) + (define tmp (cons 0 0)) + (let loop ([a-port a-port] [done 0]) (if (not a-port) (list A B C D) - (let-values ([(b-port done) (read-block! a-port done X)] - [(AA) A] [(BB) B] [(CC) C] [(DD) D]) + (let-values ([(b-port done) (read-block! a-port done X)]) (define-syntax step (syntax-rules () [(_ a b c d e f g h) + #| This is the `no GC version' (aka C-in-Scheme) of this: (set! a (word+ b (word<<< (word+ (word+ a (e b c d)) (word+ (vector-ref X f) (word g))) - h)))])) + h))) + |# + (begin (e tmp b c d) + (word+=! a tmp) + (word+=! a (vector-ref X f)) + (word+=! a (word g)) + (word<<