Configure the workloads of the benchmarks and the size of the shared heap to increase...
[IRC.git] / Robust / src / Benchmarks / Scheduling / GC / GCBench / GCBench.java
1 /** Bamboo Version  
2  * Ported by: Jin Zhou  07/14/10
3  * **/
4
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.
8
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
26 //size.
27
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.
32
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
41 //times.
42
43 //Known deficiencies:
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
49
50 task t1(StartupObject s{initialstate}) {
51   //System.printString("task t1\n");
52
53   int threadnum = 62;
54   for(int i = 0; i < threadnum; ++i) {
55     TestRunner gcb = new TestRunner(){run};
56   }
57
58   taskexit(s{!initialstate});
59 }
60
61 task t2(TestRunner gcb{run}) {
62   //System.printString("task t2\n");
63   gcb.run();
64   taskexit(gcb{!run});
65 }
66
67
68 class Node {
69   Node left, right;
70   int i, j;
71   Node(Node l, Node r) { left = l; right = r; }
72   Node() { }
73 }
74
75 public class TestRunner {
76   
77   flag run;
78
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;
84   
85   public TestRunner() {
86     kStretchTreeDepth    = 15;// 1Mb 18;  // about 16Mb
87     kLongLivedTreeDepth  = 14; // 1/4Mb 16;  // about 4Mb
88     kArraySize  = 125000; // 1/4Mb 500000;  // about 4Mb
89     kMinTreeDepth = 4;
90     kMaxTreeDepth = 16;
91   }
92
93   // Nodes used by a tree of a given size
94   int TreeSize(int i) {
95     return ((1 << (i + 1)) - 1);
96   }
97
98   // Number of iterations to use for a given tree depth
99   int NumIters(int i) {
100     return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
101   }
102
103   // Build tree top down, assigning to older objects. 
104   void Populate(int iDepth, Node thisNode) {
105     if (iDepth<=0) {
106       return;
107     } else {
108       iDepth--;
109       thisNode.left  = new Node();
110       thisNode.right = new Node();
111       Populate (iDepth, thisNode.left);
112       Populate (iDepth, thisNode.right);
113     }
114   }
115
116   // Build tree bottom-up
117   Node MakeTree(int iDepth) {
118     if (iDepth<=0) {
119       return new Node();
120     } else {
121       return new Node(MakeTree(iDepth-1),
122           MakeTree(iDepth-1));
123     }
124   }
125
126   /*static void PrintDiagnostics() {
127     long lFreeMemory = Runtime.getRuntime().freeMemory();
128     long lTotalMemory = Runtime.getRuntime().totalMemory();
129
130     System.out.print(" Total memory available="
131         + lTotalMemory + " bytes");
132     System.out.println("  Free memory=" + lFreeMemory + " bytes");
133   }*/
134
135   void TimeConstruction(int depth) {
136     Node    root;
137     //long    tStart, tFinish;
138     int         iNumIters = NumIters(depth);
139     Node        tempTree;
140
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);
147       tempTree = null;
148     }
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);
155       tempTree = null;
156     }
157     /*tFinish = System.currentTimeMillis();
158     System.out.println("\tBottom up construction took "
159         + (tFinish - tStart) + "msecs");*/
160
161   }
162   
163   public void stretch() {
164     Node    root;
165     Node    longLivedTree;
166     Node    tempTree;
167     /*long  tStart, tFinish;
168     long    tElapsed;*/
169
170
171     /*System.out.println("Garbage Collector Test");
172     System.out.println(
173         " Stretching memory with a binary tree of depth "
174         + kStretchTreeDepth);
175     PrintDiagnostics();
176     tStart = System.currentTimeMillis();*/
177
178     // Stretch the memory space quickly
179     tempTree = MakeTree(kStretchTreeDepth);
180     tempTree = null;
181   }
182
183   public void run() {
184     Node        root;
185     Node        longLivedTree;
186     
187     // Stretch the memory space quickly
188     stretch();
189
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);
196
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) {
203       array[i] = 1.0f/i;
204     }
205     //PrintDiagnostics();
206
207     for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
208       TimeConstruction(d);
209     }
210
211     if (longLivedTree == null || array[1000] != 1.0f/1000) {
212       //System.out.println("Failed");
213       System.printI(0xa0);
214       System.printI((int)(array[1000]*1000000));
215     }
216     // fake reference to LongLivedTree
217     // and array
218     // to keep them from being optimized away
219
220     /*tFinish = System.currentTimeMillis();
221     tElapsed = tFinish-tStart;
222     PrintDiagnostics();
223     System.out.println("Completed in " + tElapsed + "ms.");*/
224   }
225 } // class JavaGC