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)