2 * Ported by: Jin Zhou 07/14/10
5 //This is adapted from a benchmark written by John Ellis and Pete Kovac
6 //of Post Communications.
7 //It was modified by Hans Boehm of Silicon Graphics.
9 //This is no substitute for real applications. No actual application
10 //is likely to behave in exactly this way. However, this benchmark was
11 //designed to be more representative of real applications than other
12 //Java GC benchmarks of which we are aware.
13 //It attempts to model those properties of allocation requests that
14 //are important to current GC techniques.
15 //It is designed to be used either to obtain a single overall performance
16 //number, or to give a more detailed estimate of how collector
17 //performance varies with object lifetimes. It prints the time
18 //required to allocate and collect balanced binary trees of various
19 //sizes. Smaller trees result in shorter object lifetimes. Each cycle
20 //allocates roughly the same amount of memory.
21 //Two data structures are kept around during the entire process, so
22 //that the measured performance is representative of applications
23 //that maintain some live in-memory data. One of these is a tree
24 //containing many pointers. The other is a large array containing
25 //double precision floating point numbers. Both should be of comparable
28 //The results are only really meaningful together with a specification
29 //of how much memory was used. It is possible to trade memory for
30 //better time performance. This benchmark should be run in a 32 MB
31 //heap, though we don't currently know how to enforce that uniformly.
33 //Unlike the original Ellis and Kovac benchmark, we do not attempt
34 //measure pause times. This facility should eventually be added back
35 //in. There are several reasons for omitting it for now. The original
36 //implementation depended on assumptions about the thread scheduler
37 //that don't hold uniformly. The results really measure both the
38 //scheduler and GC. Pause time measurements tend to not fit well with
39 //current benchmark suites. As far as we know, none of the current
40 //commercial Java implementations seriously attempt to minimize GC pause
44 //- No way to check on memory use
45 //- No cyclic data structures
46 //- No attempt to measure variation with object size
47 //- Results are sensitive to locking cost, but we dont
48 //check for proper locking
50 task t1(StartupObject s{initialstate}) {
51 //System.printString("task t1\n");
54 for(int i = 0; i < threadnum; ++i) {
55 TestRunner gcb = new TestRunner(){run};
58 taskexit(s{!initialstate});
61 task t2(TestRunner gcb{run}) {
62 //System.printString("task t2\n");
71 Node(Node l, Node r) { left = l; right = r; }
75 public class TestRunner {
79 public static final int kStretchTreeDepth;// = 18; // about 16Mb
80 public static final int kLongLivedTreeDepth;// = 16; // about 4Mb
81 public static final int kArraySize;// = 500000; // about 4Mb
82 public static final int kMinTreeDepth;// = 4;
83 public static final int kMaxTreeDepth;// = 16;
86 kStretchTreeDepth = 15;// 1Mb 18; // about 16Mb
87 kLongLivedTreeDepth = 14; // 1/4Mb 16; // about 4Mb
88 kArraySize = 125000; // 1/4Mb 500000; // about 4Mb
93 // Nodes used by a tree of a given size
95 return ((1 << (i + 1)) - 1);
98 // Number of iterations to use for a given tree depth
100 return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
103 // Build tree top down, assigning to older objects.
104 void Populate(int iDepth, Node thisNode) {
109 thisNode.left = new Node();
110 thisNode.right = new Node();
111 Populate (iDepth, thisNode.left);
112 Populate (iDepth, thisNode.right);
116 // Build tree bottom-up
117 Node MakeTree(int iDepth) {
121 return new Node(MakeTree(iDepth-1),
126 /*static void PrintDiagnostics() {
127 long lFreeMemory = Runtime.getRuntime().freeMemory();
128 long lTotalMemory = Runtime.getRuntime().totalMemory();
130 System.out.print(" Total memory available="
131 + lTotalMemory + " bytes");
132 System.out.println(" Free memory=" + lFreeMemory + " bytes");
135 void TimeConstruction(int depth) {
137 //long tStart, tFinish;
138 int iNumIters = NumIters(depth);
141 /*System.out.println("Creating " + iNumIters +
142 " trees of depth " + depth);
143 tStart = System.currentTimeMillis();*/
144 for (int i = 0; i < iNumIters; ++i) {
145 tempTree = new Node();
146 Populate(depth, tempTree);
149 /*tFinish = System.currentTimeMillis();
150 System.out.println("\tTop down construction took "
151 + (tFinish - tStart) + "msecs");
152 tStart = System.currentTimeMillis();*/
153 for (int i = 0; i < iNumIters; ++i) {
154 tempTree = MakeTree(depth);
157 /*tFinish = System.currentTimeMillis();
158 System.out.println("\tBottom up construction took "
159 + (tFinish - tStart) + "msecs");*/
163 public void stretch() {
167 /*long tStart, tFinish;
171 /*System.out.println("Garbage Collector Test");
173 " Stretching memory with a binary tree of depth "
174 + kStretchTreeDepth);
176 tStart = System.currentTimeMillis();*/
178 // Stretch the memory space quickly
179 tempTree = MakeTree(kStretchTreeDepth);
187 // Stretch the memory space quickly
190 // Create a long lived object
191 /*System.out.println(
192 " Creating a long-lived binary tree of depth " +
193 kLongLivedTreeDepth);*/
194 longLivedTree = new Node();
195 Populate(kLongLivedTreeDepth, longLivedTree);
197 // Create long-lived array, filling half of it
198 /*System.out.println(
199 " Creating a long-lived array of "
200 + kArraySize + " doubles");*/
201 float array[] = new float[kArraySize];
202 for (int i = 0; i < kArraySize/2; ++i) {
205 //PrintDiagnostics();
207 for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
211 if (longLivedTree == null || array[1000] != 1.0f/1000) {
212 //System.out.println("Failed");
214 System.printI((int)(array[1000]*1000000));
216 // fake reference to LongLivedTree
218 // to keep them from being optimized away
220 /*tFinish = System.currentTimeMillis();
221 tElapsed = tFinish-tStart;
223 System.out.println("Completed in " + tElapsed + "ms.");*/