--- /dev/null
+package org.ibex.arenaj;
+// This is adapted from a benchmark written by John Ellis and Pete Kovac
+// of Post Communications.
+// It was modified by Hans Boehm of Silicon Graphics.
+//
+// This is no substitute for real applications. No actual application
+// is likely to behave in exactly this way. However, this benchmark was
+// designed to be more representative of real applications than other
+// Java GC benchmarks of which we are aware.
+// It attempts to model those properties of allocation requests that
+// are important to current GC techniques.
+// It is designed to be used either to obtain a single overall performance
+// number, or to give a more detailed estimate of how collector
+// performance varies with object lifetimes. It prints the time
+// required to allocate and collect balanced binary trees of various
+// sizes. Smaller trees result in shorter object lifetimes. Each cycle
+// allocates roughly the same amount of memory.
+// Two data structures are kept around during the entire process, so
+// that the measured performance is representative of applications
+// that maintain some live in-memory data. One of these is a tree
+// containing many pointers. The other is a large array containing
+// double precision floating point numbers. Both should be of comparable
+// size.
+//
+// The results are only really meaningful together with a specification
+// of how much memory was used. It is possible to trade memory for
+// better time performance. This benchmark should be run in a 32 MB
+// heap, though we don't currently know how to enforce that uniformly.
+//
+// Unlike the original Ellis and Kovac benchmark, we do not attempt
+// measure pause times. This facility should eventually be added back
+// in. There are several reasons for omitting it for now. The original
+// implementation depended on assumptions about the thread scheduler
+// that don't hold uniformly. The results really measure both the
+// scheduler and GC. Pause time measurements tend to not fit well with
+// current benchmark suites. As far as we know, none of the current
+// commercial Java implementations seriously attempt to minimize GC pause
+// times.
+//
+// Known deficiencies:
+// - No way to check on memory use
+// - No cyclic data structures
+// - No attempt to measure variation with object size
+// - Results are sensitive to locking cost, but we dont
+// check for proper locking
+
+public class GCBench {
+
+ public static final int kStretchTreeDepth = 18; // about 16Mb
+ public static final int kLongLivedTreeDepth = 16; // about 4Mb
+ public static final int kArraySize = 500000; // about 4Mb
+ public static final int kMinTreeDepth = 4;
+ public static final int kMaxTreeDepth = 16;
+
+ public static int zap(Object o) { return o==null ? -1 : ((Integer)o).intValue(); }
+
+ // Nodes used by a tree of a given size
+ static int TreeSize(int i) {
+ return ((1 << (i + 1)) - 1);
+ }
+
+ // Number of iterations to use for a given tree depth
+ static int NumIters(int i) {
+ return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
+ }
+
+ // Build tree top down, assigning to older objects.
+ void Populate(int iDepth) { Populate(iDepth, new Node()); }
+ void Populate(int iDepth, Node thisNode) {
+ if (iDepth<=0) {
+ return;
+ } else {
+ iDepth--;
+ thisNode.left = new Node();
+ thisNode.right = new Node();
+ Populate (iDepth, thisNode.left);
+ Populate (iDepth, thisNode.right);
+ }
+ }
+
+ // Build tree bottom-up
+ void doMakeTree(int iDepth) { MakeTree(iDepth); }
+ Node MakeTree(int iDepth) {
+ if (iDepth<=0) {
+ return new Node();
+ } else {
+ Node l = MakeTree(iDepth-1);
+ Node r = MakeTree(iDepth-1);
+ Node ret = new Node();
+ ret.left = l;
+ ret.right = r;
+ return ret;
+ }
+ }
+
+ static void PrintDiagnostics() {
+ long lFreeMemory = Runtime.getRuntime().freeMemory();
+ long lTotalMemory = Runtime.getRuntime().totalMemory();
+
+ System.out.print(" Total memory available="
+ + lTotalMemory + " bytes");
+ System.out.println(" Free memory=" + lFreeMemory + " bytes");
+ }
+
+ void TimeConstruction(int depth) {
+ Node root;
+ long tStart, tFinish;
+ int iNumIters = NumIters(depth);
+ GCBench tempTree;
+
+ System.out.println("Creating " + iNumIters +
+ " trees of depth " + depth);
+ tStart = System.currentTimeMillis();
+ for (int i = 0; i < iNumIters; ++i) {
+ tempTree = new GCBench();
+ tempTree.Populate(depth);
+ tempTree = null;
+ }
+ tFinish = System.currentTimeMillis();
+ System.out.println("\tTop down construction took "
+ + (tFinish - tStart) + "msecs");
+ tStart = System.currentTimeMillis();
+ for (int i = 0; i < iNumIters; ++i) {
+ tempTree = new GCBench();
+ tempTree.doMakeTree(depth);
+ tempTree = null;
+ }
+ tFinish = System.currentTimeMillis();
+ System.out.println("\tBottom up construction took "
+ + (tFinish - tStart) + "msecs");
+
+ }
+
+ public static void main(String args[]) {
+ Node root;
+ Node longLivedTree;
+ Node tempTree;
+ long tStart, tFinish;
+ long tElapsed;
+
+
+ System.out.println("Garbage Collector Test");
+ System.out.println(
+ " Stretching memory with a binary tree of depth "
+ + kStretchTreeDepth);
+ PrintDiagnostics();
+ tStart = System.currentTimeMillis();
+
+ // Stretch the memory space quickly
+ GCBench gcb = new GCBench();
+ gcb.doMakeTree(kStretchTreeDepth);
+ gcb = null;
+
+ // Create a long lived object
+ System.out.println(
+ " Creating a long-lived binary tree of depth " +
+ kLongLivedTreeDepth);
+ GCBench ll = new GCBench();
+ ll.Populate(kLongLivedTreeDepth);
+
+ /*
+ // Create long-lived array, filling half of it
+ System.out.println(
+ " Creating a long-lived array of "
+ + kArraySize + " doubles");
+ double array[] = new double[kArraySize];
+ for (int i = 0; i < kArraySize/2; ++i) {
+ array[i] = 1.0/i;
+ }
+ */
+ PrintDiagnostics();
+
+ for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2) {
+ ll.TimeConstruction(d);
+ }
+ /*
+ if (longLivedTree == null || array[1000] != 1.0/1000)
+ System.out.println("Failed");
+ */
+ // fake reference to LongLivedTree
+ // and array
+ // to keep them from being optimized away
+
+ tFinish = System.currentTimeMillis();
+ tElapsed = tFinish-tStart;
+ PrintDiagnostics();
+ System.out.println("Completed in " + tElapsed + "ms.");
+ }
+
+ private class Node implements Gladiator {
+ Node left, right;
+ int i, j;
+ //Node(Node l, Node r) { left = l; right = r; }
+ Node() { }
+ }
+
+} // class JavaGC