Performance and Debugging
50.1 Performance
Choose a fast implementation Chez, Gambit, CHICKEN (csc -O3), and Racket CS compile to fast native code Prefer tail recursion and iteration Constant space, fewer allocations Use vectors for random access
vector-ref is O(1); list-ref is O(n) Avoid repeated append
Build reversed lists with cons, then reverse once Use the right equality
eq?/eqv?-based tables are faster than equal? Fixnum/flonum operations
Chez fx+/fl+, R6RS (rnrs arithmetic fixnums), Racket unsafe-fx+ Avoid call/cc in hot paths
Escape-only continuations (call/1cc in Chez, let/ec in Racket) are cheaper
Build with string ports instead of repeated string-append (time expr) in Chez/Guile/Racket, profilers (Chez profile, Guile ,profile, Racket profile)
;; Slow: quadratic append
(define (squares-slow n) (let loop ((i 0) (acc '())) (if (= i n) acc (loop (+ i 1) (append acc (list (* i i)))))))
;; Fast: cons + reverse
(define (squares-fast n) (let loop ((i 0) (acc '())) (if (= i n) (reverse acc) (loop (+ i 1) (cons (* i i) acc)))))50.2 Debugging
Guile REPL meta-commands: ,help, ,describe, ,apropos, ,expand (macroexpand), ,optimize, ,disassemble, ,time, ,profile, ,trace, ,break.
;; Tracing
;; Chez: (trace f) / (untrace f), trace-define, trace-lambda
;; Guile: ,trace (f 3) at the REPL; ,break f; ,backtrace (,bt); ,locals
;; Racket: (require racket/trace) (trace f); DrRacket's stepper and debugger
;; CHICKEN: the trace egg, csi's ,b backtrace
;; Print debugging with a helper macro
(define-syntax dbg
(syntax-rules ()
((_ expr) (let ((v expr)) (write 'expr) (display " => ") (write v) (newline) v))))
(dbg (+ 1 2)) ; prints (+ 1 2) => 3, returns 3
;; Assertions
(define (assert-positive n) (unless (positive? n) (error "expected positive" n)) n)