123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
- ; Profiling
- ; NOTE: the sampling rate is set at the beginning of each run. Different
- ; machines and loadings will produce different tick rates.
- (define (profile command)
- (let ((thunk (if (eq? (car command) 'run)
- (evaluate `(lambda () ,(cadr command))
- (environment-for-commands))
- (lambda () (execute-command command)))))
- (call-with-values
- (lambda () (run-with-profiling thunk (command-output)))
- (lambda (results hits running on-stack)
- (let ((port (command-output)))
- (display hits port)
- (display " samples" port)
- (newline port)
- (display "Running:" port)
- (newline port)
- (display-counts running hits - port)
- (display "Waiting:" port)
- (newline port)
- (display-counts on-stack hits (lambda (total next) next) port)
- (set-command-results! results))))))
- (define-command-syntax 'profile "<command>" "profile execution"
- '(command))
- (define (display-counts counts hits combine port)
- (let ((limit (quotient hits 10)))
- (do ((counts counts (cdr counts))
- (total hits (combine total (cdar counts))))
- ((or (<= total limit)
- (null? counts)
- (<= (cdar counts) 1)))
- (display " " port)
- (display (cdar counts) port)
- (display " " port)
- (display (caar counts) port)
- (newline port))))
- ; Strategy:
- ; Request periodic interrupts.
- ; At each interrupt save the current (raw) continuation.
- ; Either at the end of the run or every so many interrupts, stop the
- ; timer interrupts and walk the continuations adding the templates to
- ; a table, with a count of how many times each has been seen.
- (define (run-with-profiling thunk port)
- (calculate-tick-rate! port)
- (call-with-values
- (lambda ()
- (dynamic-wind
- (lambda ()
- (vector-set! interrupt-handlers
- (enum interrupt alarm)
- handle-timer-interrupt)
- (start-periodic-interrupts!))
- (lambda ()
- (primitive-cwcc
- (lambda (top)
- (set! *top-continuation* (continuation-cont top))
- (set! *hits* 0)
- (set! *conts* '())
- (set! *templates* '())
- (set! *template-counts* (make-template-table))
- (set! *cont-counts* (make-template-table))
- (set! *cont-count* cont-limit)
- (thunk))))
- reset-timer-interrupts!))
- (lambda results
- (for-each add-cont-data! *conts*)
- (let ((templates (gather-template-table-data *template-counts*))
- (conts (gather-template-table-data *cont-counts*)))
- (set! *top-continuation* #f) ; drop pointer
- (set! *conts* '())
- (values results *hits* templates conts)))))
- (define *quantum-mantissa* #f)
- (define *quantum-exponent* #f)
- ; For checking how fast the machine is.
- (define (fib x)
- (if (< x 2)
- 1
- (+ (fib (- x 1)) (fib (- x 2)))))
- (define (calculate-tick-rate! port)
- (let ((start-time (run-time)))
- (fib 17) ; chosen more or less at random.
- (let ((end-time (run-time)))
- (set! *quantum-mantissa* (quotient (- end-time start-time) 4))
- (set! *quantum-exponent* (tick-exponent))
- (display (round (/ (* *quantum-mantissa* (expt 10 *quantum-exponent*)))) port)
- (display " ticks per second" port)
- (newline port))))
- (define (start-periodic-interrupts!)
- (schedule-interrupt *quantum-mantissa* *quantum-exponent* #t))
- (define (stop-periodic-interrupts!)
- (schedule-interrupt 0 0 #f))
- (define cont-limit 100)
- (define *cont-count* cont-limit)
- (define (handle-timer-interrupt template ei)
- (set! *cont-count* (- *cont-count* 1))
- (if (= 0 *cont-count*)
- (begin
- (stop-periodic-interrupts!)
- (for-each add-template-data! *templates*)
- (for-each add-cont-data! *conts*)
- (set! *cont-count* cont-limit)
- (set! *templates* '())
- (set! *conts* '())
- (start-periodic-interrupts!)))
- (set! *templates* (cons template *templates*))
- (set! *hits* (+ *hits* 1))
- (primitive-cwcc (lambda (cont)
- (set! *conts* (cons cont *conts*)))))
- (define *top-continuation* #f)
- (define *conts* '())
- (define *templates* '())
- (define *hits* 0)
- (define make-template-table (make-table-maker eq? template-id))
- (define *template-counts* (make-template-table))
- (define *cont-counts* (make-template-table))
- (define (okay-cont? cont)
- (and cont (not (eq? cont *top-continuation*))))
- (define (add-template-data! template)
- (let ((p (table-ref *template-counts* template)))
- (if (not p)
- (table-set! *template-counts*
- template
- (cons 1 '()))
- (set-car! p (+ (car p) 1)))))
- (define (add-cont-data! cont)
- (let loop ((cont (continuation-cont cont)))
- (if (and (okay-cont? cont)
- (okay-cont? (continuation-cont cont)))
- (let* ((template (continuation-template cont))
- (p (table-ref *cont-counts* template)))
- (if (not p)
- (table-set! *cont-counts*
- template
- (cons 1 '()))
- (set-car! p (+ (car p) 1)))
- (loop (continuation-cont cont))))))
- (define (gather-template-table-data table)
- (let ((counts '()))
- (table-walk (lambda (template p)
- (set! counts
- (cons (cons (debug-data-names
- (template-debug-data template))
- (car p))
- counts)))
- table)
- (sort-list counts
- (lambda (p1 p2)
- (>= (cdr p1) (cdr p2))))))
|