gcbench.sch 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. ; This is adapted from a benchmark written by John Ellis and Pete Kovac
  2. ; of Post Communications.
  3. ; It was modified by Hans Boehm of Silicon Graphics.
  4. ; It was translated into Scheme by William D Clinger of Northeastern Univ;
  5. ; the Scheme version uses (RUN-BENCHMARK <string> <thunk>)
  6. ; It was later hacked by Lars T Hansen of Northeastern University;
  7. ; this version has a fixed tree height but accepts a number of
  8. ; iterations to run.
  9. ;
  10. ; Modified 2000-02-15 / lth: changed gc-benchmark to only stretch once,
  11. ; and to have a different interface (now accepts iteration numbers,
  12. ; not tree height)
  13. ; Last modified 2000-07-14 / lth -- fixed a buggy comment about storage
  14. ; use in Larceny.
  15. ;
  16. ; This is no substitute for real applications. No actual application
  17. ; is likely to behave in exactly this way. However, this benchmark was
  18. ; designed to be more representative of real applications than other
  19. ; Java GC benchmarks of which we are aware.
  20. ; It attempts to model those properties of allocation requests that
  21. ; are important to current GC techniques.
  22. ; It is designed to be used either to obtain a single overall performance
  23. ; number, or to give a more detailed estimate of how collector
  24. ; performance varies with object lifetimes. It prints the time
  25. ; required to allocate and collect balanced binary trees of various
  26. ; sizes. Smaller trees result in shorter object lifetimes. Each cycle
  27. ; allocates roughly the same amount of memory.
  28. ; Two data structures are kept around during the entire process, so
  29. ; that the measured performance is representative of applications
  30. ; that maintain some live in-memory data. One of these is a tree
  31. ; containing many pointers. The other is a large array containing
  32. ; double precision floating point numbers. Both should be of comparable
  33. ; size.
  34. ;
  35. ; The results are only really meaningful together with a specification
  36. ; of how much memory was used. It is possible to trade memory for
  37. ; better time performance. This benchmark should be run in a 32 MB
  38. ; heap, though we don't currently know how to enforce that uniformly.
  39. ; In the Java version, this routine prints the heap size and the amount
  40. ; of free memory. There is no portable way to do this in Scheme; each
  41. ; implementation needs its own version.
  42. (define (PrintDiagnostics)
  43. (display " Total memory available= ???????? bytes")
  44. (display " Free memory= ???????? bytes")
  45. (newline))
  46. (define (yes answer) #t)
  47. ; Should we implement a Java class as procedures or hygienic macros?
  48. ; Take your pick.
  49. (define-syntax let-class
  50. (syntax-rules
  51. ()
  52. ; Put this rule first to implement a class using hygienic macros.
  53. ((let-class (((method . args) . method-body) ...) . body)
  54. (letrec-syntax ((method (syntax-rules ()
  55. ((method . args) (begin . method-body))))
  56. ...)
  57. . body))
  58. ; Put this rule first to implement a class using procedures.
  59. ((let-class (((method . args) . method-body) ...) . body)
  60. (let () (define (method . args) . method-body) ... . body))
  61. ))
  62. (define stretch #t) ; Controls whether stretching phase is run
  63. (define (gcbench kStretchTreeDepth)
  64. ; Use for inner calls to reduce noise.
  65. (define (run-benchmark name iters thunk test)
  66. (do ((i 0 (+ i 1)))
  67. ((= i iters))
  68. (thunk)))
  69. ; Nodes used by a tree of a given size
  70. (define (TreeSize i)
  71. (- (expt 2 (+ i 1)) 1))
  72. ; Number of iterations to use for a given tree depth
  73. (define (NumIters i)
  74. (quotient (* 2 (TreeSize kStretchTreeDepth))
  75. (TreeSize i)))
  76. ; Parameters are determined by kStretchTreeDepth.
  77. ; In Boehm's version the parameters were fixed as follows:
  78. ; public static final int kStretchTreeDepth = 18; // about 16Mb
  79. ; public static final int kLongLivedTreeDepth = 16; // about 4Mb
  80. ; public static final int kArraySize = 500000; // about 4Mb
  81. ; public static final int kMinTreeDepth = 4;
  82. ; public static final int kMaxTreeDepth = 16;
  83. ; wdc: In Larceny the storage numbers above would be 12 Mby, 3 Mby, 6 Mby.
  84. ; lth: No they would not. A flonum requires 16 bytes, so the size
  85. ; of array + flonums would be 500,000*4 + 500,000*16=10 Mby.
  86. (let* ((kLongLivedTreeDepth (- kStretchTreeDepth 2))
  87. (kArraySize (* 4 (TreeSize kLongLivedTreeDepth)))
  88. (kMinTreeDepth 4)
  89. (kMaxTreeDepth kLongLivedTreeDepth))
  90. ; Elements 3 and 4 of the allocated vectors are useless.
  91. (let-class (((make-node l r)
  92. (let ((v (make-empty-node)))
  93. (vector-set! v 0 l)
  94. (vector-set! v 1 r)
  95. v))
  96. ((make-empty-node) (make-vector 4 0))
  97. ((node.left node) (vector-ref node 0))
  98. ((node.right node) (vector-ref node 1))
  99. ((node.left-set! node x) (vector-set! node 0 x))
  100. ((node.right-set! node x) (vector-set! node 1 x)))
  101. ; Build tree top down, assigning to older objects.
  102. (define (Populate iDepth thisNode)
  103. (if (<= iDepth 0)
  104. #f
  105. (let ((iDepth (- iDepth 1)))
  106. (node.left-set! thisNode (make-empty-node))
  107. (node.right-set! thisNode (make-empty-node))
  108. (Populate iDepth (node.left thisNode))
  109. (Populate iDepth (node.right thisNode)))))
  110. ; Build tree bottom-up
  111. (define (MakeTree iDepth)
  112. (if (<= iDepth 0)
  113. (make-empty-node)
  114. (make-node (MakeTree (- iDepth 1))
  115. (MakeTree (- iDepth 1)))))
  116. (define (TimeConstruction depth)
  117. (let ((iNumIters (NumIters depth)))
  118. (display (string-append "Creating "
  119. (number->string iNumIters)
  120. " trees of depth "
  121. (number->string depth)))
  122. (newline)
  123. (run-benchmark "GCBench: Top down construction"
  124. 1
  125. (lambda ()
  126. (do ((i 0 (+ i 1)))
  127. ((>= i iNumIters))
  128. (Populate depth (make-empty-node))))
  129. yes)
  130. (run-benchmark "GCBench: Bottom up construction"
  131. 1
  132. (lambda ()
  133. (do ((i 0 (+ i 1)))
  134. ((>= i iNumIters))
  135. (MakeTree depth)))
  136. yes)))
  137. (define (main)
  138. (display "Garbage Collector Test")
  139. (newline)
  140. (if stretch
  141. (begin
  142. (display (string-append
  143. " Stretching memory with a binary tree of depth "
  144. (number->string kStretchTreeDepth)))
  145. (newline)))
  146. (PrintDiagnostics)
  147. (run-benchmark "GCBench: Main"
  148. 1
  149. (lambda ()
  150. ; Stretch the memory space quickly
  151. (if stretch
  152. (MakeTree kStretchTreeDepth))
  153. ; Create a long lived object
  154. (display
  155. (string-append
  156. " Creating a long-lived binary tree of depth "
  157. (number->string kLongLivedTreeDepth)))
  158. (newline)
  159. (let ((longLivedTree (make-empty-node)))
  160. (Populate kLongLivedTreeDepth longLivedTree)
  161. ; Create long-lived array, filling half of it
  162. (display (string-append
  163. " Creating a long-lived array of "
  164. (number->string kArraySize)
  165. " inexact reals"))
  166. (newline)
  167. (let ((array (make-vector kArraySize 0.0)))
  168. (do ((i 0 (+ i 1)))
  169. ((>= i (quotient kArraySize 2)))
  170. (vector-set! array i
  171. (/ 1.0 (exact->inexact i))))
  172. (PrintDiagnostics)
  173. (do ((d kMinTreeDepth (+ d 2)))
  174. ((> d kMaxTreeDepth))
  175. (TimeConstruction d))
  176. (if (or (eq? longLivedTree '())
  177. (let ((n (min 1000
  178. (- (quotient (vector-length array)
  179. 2)
  180. 1))))
  181. (not (= (vector-ref array n)
  182. (/ 1.0 (exact->inexact n))))))
  183. (begin (display "Failed") (newline)))
  184. ; fake reference to LongLivedTree
  185. ; and array
  186. ; to keep them from being optimized away
  187. )))
  188. yes)
  189. (PrintDiagnostics))
  190. (main))))
  191. (define (gc-benchmark . rest)
  192. (let ((k 18)
  193. (n (if (null? rest) 1 (car rest))))
  194. (display "The garbage collector should touch about ")
  195. (display (expt 2 (- k 13)))
  196. (display " megabytes of heap storage.")
  197. (newline)
  198. (display "The use of more or less memory will skew the results.")
  199. (newline)
  200. (set! stretch #t)
  201. (run-benchmark (string-append "GCBench" (number->string k))
  202. n
  203. (lambda ()
  204. (gcbench k)
  205. (set! stretch #f))
  206. yes)
  207. (set! stretch #t)))