* configure.ac: New switch for disabling -O2 (--disable-optimizations).
[cacao.git] / tests / GCBench.java
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 //
5 //      This is no substitute for real applications.  No actual application
6 //      is likely to behave in exactly this way.  However, this benchmark was
7 //      designed to be more representative of real applications than other
8 //      Java GC benchmarks of which we are aware.
9 //      It attempts to model those properties of allocation requests that
10 //      are important to current GC techniques.
11 //      It is designed to be used either to obtain a single overall performance
12 //      number, or to give a more detailed estimate of how collector
13 //      performance varies with object lifetimes.  It prints the time
14 //      required to allocate and collect balanced binary trees of various
15 //      sizes.  Smaller trees result in shorter object lifetimes.  Each cycle
16 //      allocates roughly the same amount of memory.
17 //      Two data structures are kept around during the entire process, so
18 //      that the measured performance is representative of applications
19 //      that maintain some live in-memory data.  One of these is a tree
20 //      containing many pointers.  The other is a large array containing
21 //      double precision floating point numbers.  Both should be of comparable
22 //      size.
23 //
24 //      The results are only really meaningful together with a specification
25 //      of how much memory was used.  It is possible to trade memory for
26 //      better time performance.  This benchmark should be run in a 32 MB
27 //      heap, though we don't currently know how to enforce that uniformly.
28 //
29 //      Unlike the original Ellis and Kovac benchmark, we do not attempt
30 //      measure pause times.  This facility should eventually be added back
31 //      in.  There are several reasons for omitting it for now.  The original
32 //      implementation depended on assumptions about the thread scheduler
33 //      that don't hold uniformly.  The results really measure both the
34 //      scheduler and GC.  Pause time measurements tend to not fit well with
35 //      current benchmark suites.  As far as we know, none of the current
36 //      commercial Java implementations seriously attempt to minimize GC pause
37 //      times.
38 //
39 //      Known deficiencies:
40 //              - No way to check on memory use
41 //              - No cyclic data structures
42 //              - No attempt to measure variation with object size
43 //              - Results are sensitive to locking cost, but we dont
44 //                check for proper locking
45
46 class Node {
47         Node left, right;
48         int i, j;
49         Node(Node l, Node r) { left = l; right = r; }
50         Node() { }
51 }
52
53 public class GCBench {
54
55         public static final int kStretchTreeDepth    = 18;      // about 16Mb
56         public static final int kLongLivedTreeDepth  = 16;  // about 4Mb
57         public static final int kArraySize  = 500000;  // about 4Mb
58         public static final int kMinTreeDepth = 4;
59         public static final int kMaxTreeDepth = 16;
60
61         // Nodes used by a tree of a given size
62         static int TreeSize(int i) {
63                 return ((1 << (i + 1)) - 1);
64         }
65
66         // Number of iterations to use for a given tree depth
67         static int NumIters(int i) {
68                 return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
69         }
70
71         // Build tree top down, assigning to older objects. 
72         static void Populate(int iDepth, Node thisNode) {
73                 if (iDepth<=0) {
74                         return;
75                 } else {
76                         iDepth--;
77                         thisNode.left  = new Node();
78                         thisNode.right = new Node();
79                         Populate (iDepth, thisNode.left);
80                         Populate (iDepth, thisNode.right);
81                 }
82         }
83
84         // Build tree bottom-up
85         static Node MakeTree(int iDepth) {
86                 if (iDepth<=0) {
87                         return new Node();
88                 } else {
89                         return new Node(MakeTree(iDepth-1),
90                                         MakeTree(iDepth-1));
91                 }
92         }
93
94         static void PrintDiagnostics() {
95                 long lFreeMemory = Runtime.getRuntime().freeMemory();
96                 long lTotalMemory = Runtime.getRuntime().totalMemory();
97
98                 System.out.print(" Total memory available="
99                                  + lTotalMemory + " bytes");
100                 System.out.println("  Free memory=" + lFreeMemory + " bytes");
101         }
102
103         static void TimeConstruction(int depth) {
104                 Node    root;
105                 long    tStart, tFinish;
106                 int     iNumIters = NumIters(depth);
107                 Node    tempTree;
108
109                 System.out.println("Creating " + iNumIters +
110                                    " trees of depth " + depth);
111                 tStart = System.currentTimeMillis();
112                 for (int i = 0; i < iNumIters; ++i) {
113                         tempTree = new Node();
114                         Populate(depth, tempTree);
115                         tempTree = null;
116                 }
117                 tFinish = System.currentTimeMillis();
118                 System.out.println("\tTop down construction took "
119                                    + (tFinish - tStart) + "msecs");
120                 tStart = System.currentTimeMillis();
121                 for (int i = 0; i < iNumIters; ++i) {
122                         tempTree = MakeTree(depth);
123                         tempTree = null;
124                 }
125                 tFinish = System.currentTimeMillis();
126                 System.out.println("\tBottom up construction took "
127                                    + (tFinish - tStart) + "msecs");
128                 
129         }
130
131         public static void main(String args[]) {
132                 Node    root;
133                 Node    longLivedTree;
134                 Node    tempTree;
135                 long    tStart, tFinish;
136                 long    tElapsed;
137
138
139                 System.out.println("Garbage Collector Test");
140                 System.out.println(
141                         " Stretching memory with a binary tree of depth "
142                         + kStretchTreeDepth);
143                 PrintDiagnostics();
144                 tStart = System.currentTimeMillis();
145
146                 // Stretch the memory space quickly
147                 tempTree = MakeTree(kStretchTreeDepth);
148                 tempTree = null;
149
150                 // Create a long lived object
151                 System.out.println(
152                         " Creating a long-lived binary tree of depth " +
153                         kLongLivedTreeDepth);
154                 longLivedTree = new Node();
155                 Populate(kLongLivedTreeDepth, longLivedTree);
156
157                 // Create long-lived array, filling half of it
158                 System.out.println(
159                         " Creating a long-lived array of "
160                         + kArraySize + " doubles");
161                 double array[] = new double[kArraySize];
162                 for (int i = 0; i < kArraySize/2; ++i) {
163                         array[i] = 1.0/(i+1);
164                 }
165                 PrintDiagnostics();
166
167                 for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
168                         TimeConstruction(d);
169                 }
170
171                 if (longLivedTree == null || array[1000] != 1.0/1001)
172                         System.out.println("Failed");
173                                         // fake reference to LongLivedTree
174                                         // and array
175                                         // to keep them from being optimized away
176
177                 tFinish = System.currentTimeMillis();
178                 tElapsed = tFinish-tStart;
179                 PrintDiagnostics();
180                 System.out.println("Completed in " + tElapsed + "ms.");
181         }
182 } // class JavaGC