3 //This is adapted from a benchmark written by John Ellis and Pete Kovac
4 //of Post Communications.
5 //It was modified by Hans Boehm of Silicon Graphics.
7 //This is no substitute for real applications. No actual application
8 //is likely to behave in exactly this way. However, this benchmark was
9 //designed to be more representative of real applications than other
10 //Java GC benchmarks of which we are aware.
11 //It attempts to model those properties of allocation requests that
12 //are important to current GC techniques.
13 //It is designed to be used either to obtain a single overall performance
14 //number, or to give a more detailed estimate of how collector
15 //performance varies with object lifetimes. It prints the time
16 //required to allocate and collect balanced binary trees of various
17 //sizes. Smaller trees result in shorter object lifetimes. Each cycle
18 //allocates roughly the same amount of memory.
19 //Two data structures are kept around during the entire process, so
20 //that the measured performance is representative of applications
21 //that maintain some live in-memory data. One of these is a tree
22 //containing many pointers. The other is a large array containing
23 //double precision floating point numbers. Both should be of comparable
26 //The results are only really meaningful together with a specification
27 //of how much memory was used. It is possible to trade memory for
28 //better time performance. This benchmark should be run in a 32 MB
29 //heap, though we don't currently know how to enforce that uniformly.
31 //Unlike the original Ellis and Kovac benchmark, we do not attempt
32 //measure pause times. This facility should eventually be added back
33 //in. There are several reasons for omitting it for now. The original
34 //implementation depended on assumptions about the thread scheduler
35 //that don't hold uniformly. The results really measure both the
36 //scheduler and GC. Pause time measurements tend to not fit well with
37 //current benchmark suites. As far as we know, none of the current
38 //commercial Java implementations seriously attempt to minimize GC pause
42 //- No way to check on memory use
43 //- No cyclic data structures
44 //- No attempt to measure variation with object size
45 //- Results are sensitive to locking cost, but we dont
46 //check for proper locking
48 public class TestRunner extends Thread {
50 public static final int kStretchTreeDepth = 16; // about 4Mb
51 public static final int kLongLivedTreeDepth = 14; // about 1Mb
52 public static final int kArraySize = 250000; // about 1Mb
53 public static final int kMinTreeDepth = 4;
54 public static final int kMaxTreeDepth = 14;
56 // Nodes used by a tree of a given size
58 return ((1 << (i + 1)) - 1);
61 // Number of iterations to use for a given tree depth
63 return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
66 // Build tree top down, assigning to older objects.
67 void Populate(int iDepth, Node thisNode) {
72 thisNode.left = new Node();
73 thisNode.right = new Node();
74 Populate (iDepth, thisNode.left);
75 Populate (iDepth, thisNode.right);
79 // Build tree bottom-up
80 Node MakeTree(int iDepth) {
84 return new Node(MakeTree(iDepth-1),
90 Node tempTree = new Node();
91 Populate(depth, tempTree);
96 Node tempTree = MakeTree(depth);
100 void TimeConstruction(int depth) {
102 int iNumIters = NumIters(depth);
105 for (int i = 0; i < iNumIters; ++i) {
108 for (int i = 0; i < iNumIters; ++i) {
113 public void stretch() {
118 // Stretch the memory space quickly
119 tempTree = MakeTree(kStretchTreeDepth);
127 // Stretch the memory space quickly
130 // Create a long lived object
131 longLivedTree = new Node();
132 Populate(kLongLivedTreeDepth, longLivedTree);
134 // Create long-lived array, filling half of it
135 float array[] = new float[kArraySize];
136 for (int i = 0; i < kArraySize/2; ++i) {
140 for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
144 if (longLivedTree == null || array[1000] != 1.0f/1000) {
145 System.out.println(0xa0);
146 System.out.println((int)(array[1000]*1000000));
150 public static void main(String[] args) {
151 int threadnum = THREADNUM;
152 System.setgcprofileflag();
153 for(int i = 0; i < threadnum; ++i) {
154 TestRunner tr = new TestRunner();