/* * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
package gc.stress.gcold;
import java.text.*; import java.util.Random;
import jdk.test.lib.Utils;
class TreeNode { public TreeNode left, right; publicint val; // will always be the height of the tree
}
/* Args: live-data-size: in megabytes (approximate, will be rounded down). work: units of mutator non-allocation work per byte allocated, (in unspecified units. This will affect the promotion rate printed at the end of the run: more mutator work per step implies fewer steps per second implies fewer bytes promoted per second.) short/long ratio: ratio of short-lived bytes allocated to long-lived bytes allocated. pointer mutation rate: number of pointer mutations per step. steps: number of steps to do.
*/
privatestaticfinal String msg1
= "Usage: java TestGCOld "; privatestaticfinal String msg2
= " where is the live storage in megabytes"; privatestaticfinal String msg3
= " is the mutator work per step (arbitrary units)"; privatestaticfinal String msg4
= " is the ratio of short-lived to long-lived allocation"; privatestaticfinal String msg5
= " is the mutations per step"; privatestaticfinal String msg6
= " is the number of steps";
// Counters (and global variables that discourage optimization)
privatestaticlong youngBytes = 0; // total young bytes allocated privatestaticlong nodes = 0; // total tree nodes allocated privatestaticlong actuallyMut = 0; // pointer mutations in old trees privatestaticlong mutatorSum = 0; // checksum to discourage optimization publicstaticint[] aexport; // exported array to discourage opt
// Global variables.
privatestatic TreeNode[] trees; privatestaticint where = 0; // roving index into trees privatestatic Random rnd = Utils.getRandomInstance();
// Given a balanced tree full and a smaller balanced tree partial, // replaces an appropriate subtree of full by partial, taking care // to preserve the shape of the full tree.
// Allocates approximately n bytes of long-lived storage, // replacing oldest existing long-lived storage.
privatestaticvoid oldGenAlloc(long n) { int full = (int) (n / treeSize); long partial = n % treeSize; // System.out.println("In oldGenAlloc, doing " + full + " full trees " // + "and one partial tree of size " + partial); for (int i = 0; i < full; i++) {
trees[where++] = makeTree(treeHeight); if (where == trees.length) where = 0;
} while (partial > INSIGNIFICANT) { int h = bytesToHeight(partial);
TreeNode newTree = makeTree(h);
replaceTree(trees[where++], newTree); if (where == trees.length) where = 0;
partial = partial - heightToBytes(h);
}
}
// Interchanges two randomly selected subtrees (of same size and depth).
privatestaticvoid oldGenSwapSubtrees() { // Randomly pick: // * two tree indices // * A depth // * A path to that depth. int index1 = rnd.nextInt(trees.length); int index2 = rnd.nextInt(trees.length); int depth = rnd.nextInt(treeHeight); int path = rnd.nextInt();
TreeNode tn1 = trees[index1];
TreeNode tn2 = trees[index2]; for (int i = 0; i < depth; i++) { if ((path & 1) == 0) {
tn1 = tn1.left;
tn2 = tn2.left;
} else {
tn1 = tn1.right;
tn2 = tn2.right;
}
path >>= 1;
}
TreeNode tmp; if ((path & 1) == 0) {
tmp = tn1.left;
tn1.left = tn2.left;
tn2.left = tmp;
} else {
tmp = tn1.right;
tn1.right = tn2.right;
tn2.right = tmp;
}
actuallyMut += 2;
}
// Update "n" old-generation pointers.
privatestaticvoid oldGenMut(long n) { for (int i = 0; i < n/2; i++) {
oldGenSwapSubtrees();
}
}
// Does the amount of mutator work appropriate for n bytes of young-gen // garbage allocation.
privatestaticvoid doMutWork(long n) { int sum = 0; long limit = workUnits*n/10; for (long k = 0; k < limit; k++) sum++; // We don't want dead code elimination to eliminate the loop above.
mutatorSum = mutatorSum + sum;
}
// Allocate n bytes of young-gen garbage, in units of "nwords" // words.
privatestaticvoid doYoungGenAlloc(long n, int nwords) { finalint nbytes = nwords*BYTES_PER_WORD; int allocated = 0; while (allocated < n) {
aexport = newint[nwords]; /* System.err.println("Step"); */
allocated += nbytes;
}
youngBytes = youngBytes + allocated;
}
// Allocate "n" bytes of young-gen data; and do the // corresponding amount of old-gen allocation and pointer // mutation.
// oldGenAlloc may perform some mutations, so this code // takes those mutations into account.
privatestaticvoid doStep(long n) { long mutations = actuallyMut;
System.out.println(size + " megabytes of live storage");
System.out.println(workUnits + " work units per step");
System.out.println("promotion ratio is 1:" + promoteRate);
System.out.println("pointer mutation rate is " + ptrMutRate);
System.out.println(steps + " steps");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.