gcbench.nim 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. discard """
  2. outputsub: "Success!"
  3. """
  4. # This is adapted from a benchmark written by John Ellis and Pete Kovac
  5. # of Post Communications.
  6. # It was modified by Hans Boehm of Silicon Graphics.
  7. #
  8. # This is no substitute for real applications. No actual application
  9. # is likely to behave in exactly this way. However, this benchmark was
  10. # designed to be more representative of real applications than other
  11. # Java GC benchmarks of which we are aware.
  12. # It attempts to model those properties of allocation requests that
  13. # are important to current GC techniques.
  14. # It is designed to be used either to obtain a single overall performance
  15. # number, or to give a more detailed estimate of how collector
  16. # performance varies with object lifetimes. It prints the time
  17. # required to allocate and collect balanced binary trees of various
  18. # sizes. Smaller trees result in shorter object lifetimes. Each cycle
  19. # allocates roughly the same amount of memory.
  20. # Two data structures are kept around during the entire process, so
  21. # that the measured performance is representative of applications
  22. # that maintain some live in-memory data. One of these is a tree
  23. # containing many pointers. The other is a large array containing
  24. # double precision floating point numbers. Both should be of comparable
  25. # size.
  26. #
  27. # The results are only really meaningful together with a specification
  28. # of how much memory was used. It is possible to trade memory for
  29. # better time performance. This benchmark should be run in a 32 MB
  30. # heap, though we don't currently know how to enforce that uniformly.
  31. #
  32. # Unlike the original Ellis and Kovac benchmark, we do not attempt
  33. # measure pause times. This facility should eventually be added back
  34. # in. There are several reasons for omitting it for now. The original
  35. # implementation depended on assumptions about the thread scheduler
  36. # that don't hold uniformly. The results really measure both the
  37. # scheduler and GC. Pause time measurements tend to not fit well with
  38. # current benchmark suites. As far as we know, none of the current
  39. # commercial Java implementations seriously attempt to minimize GC pause
  40. # times.
  41. #
  42. # Known deficiencies:
  43. # - No way to check on memory use
  44. # - No cyclic data structures
  45. # - No attempt to measure variation with object size
  46. # - Results are sensitive to locking cost, but we dont
  47. # check for proper locking
  48. #
  49. import
  50. strutils, times
  51. type
  52. PNode = ref TNode
  53. TNode {.final.} = object
  54. left, right: PNode
  55. i, j: int
  56. proc newNode(L, r: PNode): PNode =
  57. new(result)
  58. result.left = L
  59. result.right = r
  60. const
  61. kStretchTreeDepth = 18 # about 16Mb
  62. kLongLivedTreeDepth = 16 # about 4Mb
  63. kArraySize = 500000 # about 4Mb
  64. kMinTreeDepth = 4
  65. kMaxTreeDepth = 16
  66. # Nodes used by a tree of a given size
  67. proc TreeSize(i: int): int = return ((1 shl (i + 1)) - 1)
  68. # Number of iterations to use for a given tree depth
  69. proc NumIters(i: int): int =
  70. return 2 * TreeSize(kStretchTreeDepth) div TreeSize(i)
  71. # Build tree top down, assigning to older objects.
  72. proc Populate(iDepth: int, thisNode: PNode) =
  73. if iDepth <= 0:
  74. return
  75. else:
  76. new(thisNode.left)
  77. new(thisNode.right)
  78. Populate(iDepth-1, thisNode.left)
  79. Populate(iDepth-1, thisNode.right)
  80. # Build tree bottom-up
  81. proc MakeTree(iDepth: int): PNode =
  82. if iDepth <= 0:
  83. new(result)
  84. else:
  85. return newNode(MakeTree(iDepth-1), MakeTree(iDepth-1))
  86. proc PrintDiagnostics() =
  87. echo("Total memory available: " & $getTotalMem() & " bytes")
  88. echo("Free memory: " & $getFreeMem() & " bytes")
  89. proc TimeConstruction(depth: int) =
  90. var
  91. root, tempTree: PNode
  92. iNumIters: int
  93. iNumIters = NumIters(depth)
  94. echo("Creating " & $iNumIters & " trees of depth " & $depth)
  95. var t = epochTime()
  96. for i in 0..iNumIters-1:
  97. new(tempTree)
  98. Populate(depth, tempTree)
  99. tempTree = nil
  100. echo("\tTop down construction took " & $(epochTime() - t) & "msecs")
  101. t = epochTime()
  102. for i in 0..iNumIters-1:
  103. tempTree = MakeTree(depth)
  104. tempTree = nil
  105. echo("\tBottom up construction took " & $(epochTime() - t) & "msecs")
  106. type
  107. tMyArray = seq[float]
  108. proc main() =
  109. var
  110. root, longLivedTree, tempTree: PNode
  111. myarray: tMyArray
  112. echo("Garbage Collector Test")
  113. echo(" Stretching memory with a binary tree of depth " & $kStretchTreeDepth)
  114. PrintDiagnostics()
  115. var t = epochTime()
  116. # Stretch the memory space quickly
  117. tempTree = MakeTree(kStretchTreeDepth)
  118. tempTree = nil
  119. # Create a long lived object
  120. echo(" Creating a long-lived binary tree of depth " &
  121. $kLongLivedTreeDepth)
  122. new(longLivedTree)
  123. Populate(kLongLivedTreeDepth, longLivedTree)
  124. # Create long-lived array, filling half of it
  125. echo(" Creating a long-lived array of " & $kArraySize & " doubles")
  126. newSeq(myarray, kArraySize)
  127. for i in 0..kArraySize div 2 - 1:
  128. myarray[i] = 1.0 / toFloat(i)
  129. PrintDiagnostics()
  130. var d = kMinTreeDepth
  131. while d <= kMaxTreeDepth:
  132. TimeConstruction(d)
  133. inc(d, 2)
  134. if longLivedTree == nil or myarray[1000] != 1.0/1000.0:
  135. echo("Failed")
  136. # fake reference to LongLivedTree
  137. # and array to keep them from being optimized away
  138. var elapsed = epochTime() - t
  139. PrintDiagnostics()
  140. echo("Completed in " & $elapsed & "ms. Success!")
  141. when defined(GC_setMaxPause):
  142. GC_setMaxPause 2_000
  143. main()