profile.scm 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; This was a fun hack, but I didn't get much useful information out of
  3. ; it -- a profiler that only samples at points allowed by the VM's
  4. ; interrupt mechanism doesn't tell you what you want to know. The
  5. ; only information available at that point is the continuation; what
  6. ; we really want to know is where the PC has been. In particular, the
  7. ; only procedures that show up in the table at all are those that call
  8. ; other procedures. JAR 12/92
  9. '
  10. (define-structure profiler (export profile)
  11. (open scheme-level-2 handle vm-exception ;interrupts
  12. architecture continuation simple-signals condition template
  13. table structure-refs debug-data sort
  14. clock) ;schedule-interrupt
  15. (files (misc profile)))
  16. (define (profile thunk frequency)
  17. (let ((table (make-table template-uid))
  18. (dt (round (/ (expt 10 6) frequency))))
  19. (primitive-catch
  20. (lambda (k0)
  21. (let ((foo (continuation-template k0)))
  22. (with-handler
  23. (lambda (c punt)
  24. (if (and (interrupt-condition? c)
  25. (eqv? (interrupt-source c) interrupt/alarm))
  26. (primitive-catch
  27. (lambda (k)
  28. (record-profile-information! k foo table)
  29. (schedule-interrupt dt)))
  30. (punt)))
  31. (lambda ()
  32. (dynamic-wind (lambda () (schedule-interrupt dt -6))
  33. thunk
  34. (lambda () (schedule-interrupt 0 1))))))))
  35. table))
  36. (define (record-profile-information! k k0-template table)
  37. (let ((k1 (continuation-cont (continuation-cont k))))
  38. (let ((z (get-counts table k1)))
  39. (set-car! z (+ (car z) 1))
  40. (set-cdr! z (+ (cdr z) 1)))
  41. (do ((k (continuation-cont k1) (continuation-cont k)))
  42. ((or (not (continuation? k))
  43. (eq? (continuation-template k) k0-template)))
  44. (let ((z (get-counts table k)))
  45. (set-cdr! z (+ (cdr z) 1))))))
  46. (define (get-counts table k)
  47. (let ((info (template-info (continuation-template k))))
  48. (or (table-ref table info)
  49. (let ((z (cons 0 0)))
  50. (table-set! table info z)
  51. z))))
  52. (define (template-uid info)
  53. (cond ((integer? info)
  54. info)
  55. ((debug-data? info)
  56. (debug-data-uid info))
  57. (else 0))) ;??
  58. (define interrupt-type cadr)
  59. (define interrupt/alarm (enum interrupt alarm))
  60. (define (dump t)
  61. (let ((l '()))
  62. (table-walk (lambda (key count)
  63. (let ((dd (if (integer? key)
  64. (table-ref debug-data-table key)
  65. key)))
  66. (set! l (cons (cons count
  67. (if (debug-data? dd)
  68. (debug-data-names dd)
  69. `(? ,key)))
  70. l))))
  71. t)
  72. (do ((l (sort-list l more-interesting?)
  73. (cdr l))
  74. (i 0 (+ i 1)))
  75. ((or (null? l) (> i *prefix*)))
  76. (let* ((counts+names (car l))
  77. (leaf-count (caar counts+names))
  78. (total-count (cdar counts+names))
  79. (names (cdr counts+names)))
  80. (display (pad-left total-count 6)) (display #\space)
  81. (display (pad-left leaf-count 6)) (display #\space)
  82. (write names)
  83. (newline)))))
  84. (define (more-interesting? x y)
  85. (let ((c1 (cdar x))
  86. (c2 (cdar y)))
  87. (or (> c1 c2)
  88. (and (= c1 c2)
  89. (> (caar x) (caar y))))))
  90. (define *prefix* 60)
  91. (define (pad-left s n)
  92. (let ((s (cond ((number? s) (number->string s))
  93. ((symbol? s) (symbol->string s))
  94. (else s))))
  95. (string-append (make-string (- n (string-length s)) #\space)
  96. s)))