Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
41161 views
/*1* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package nsk.share.gc;2425import nsk.share.test.LocalRandom;26import java.io.PrintStream;27import nsk.share.gc.gp.GarbageProducer;28import nsk.share.gc.tree.*;29import nsk.share.gc.gp.MemoryStrategy;30import nsk.share.log.Log;3132/**33* Different utility methods to work with memory objects.34*/35public final class Memory {36private static int bits = 0;37private static int referenceSize = 0;38private static int objectExtraSize = 0;3940private Memory() {41}4243private static int getBits() {44if (bits == 0)45bits = Integer.parseInt(System.getProperty("sun.arch.data.model"));46return bits;47}4849/**50* Get size of one object reference.51*52* TODO: somehow determine the real value53*/54public static int getReferenceSize() {55if (referenceSize == 0)56referenceSize = (getBits() == 64) ? 8 : 4;57return referenceSize;58}5960/**61* Get size of primitive type int.62*/63public static int getIntSize() {64return 4;65}6667/**68* Get size of primitive type boolean.69*/70public static int getBooleanSize() {71return 1;72}7374/**75* Get size of primitive type byte.76*/77public static int getByteSize() {78return 1;79}8081/**82* Get size of primitive type char.83*/84public static int getCharSize() {85return 2;86}8788/**89* Get size of primitive type short.90*/91public static int getShortSize() {92return 2;93}9495/**96* Get size of primitive type long.97*/98public static int getLongSize() {99return 8;100}101102/**103* Get size of primitive type float.104*/105public static int getFloatSize() {106return 4;107}108109/**110* Get size of primitive type double.111*/112public static int getDoubleSize() {113return 8;114}115116/**117* Get how many extra bytes an object occupies in the heap118* compared to sum of it's fields.119*120* TODO: somehow determine the real value121*/122public static int getObjectExtraSize() {123if (objectExtraSize == 0)124objectExtraSize = 2 * getReferenceSize();125return objectExtraSize;126}127/**128* Get how many extra bytes an array occupies in the heap129* compared to sum of it's fields.130*131* TODO: somehow determine the real value132*/133public static int getArrayExtraSize() {134return getObjectExtraSize();135}136137/**138* Return size of reference object (SoftReference, WeakReference, PhantomReference)139*/140public static int getReferenceObjectSize() {141return getReferenceSize() + getObjectExtraSize();142}143144/**145* Get an approximate length of array that will occupy a given memory.146*147* @param memory size of memory148* @param objectSize size of each object in array149* @return length of array150*/151public static int getArrayLength(long memory, long objectSize) {152int referenceSize = getReferenceSize();153int arrayExtraSize = getArrayExtraSize();154return (int) Math.min(155(memory - arrayExtraSize) / (objectSize + referenceSize),156Integer.MAX_VALUE157);158}159160/**161* Get an approximate size of array of given length and object size.162*163* @param length length of arary164* @param objectSize size of object in array165* @return size of array166*/167public static long getArraySize(int length, long objectSize) {168return getObjectExtraSize() + length * (objectSize + getReferenceSize());169}170171/**172* Calculate approximate size of biggest of MemoryObjects.173*/174public static long getMemoryObjectSize(long size) {175return size + 2 * getReferenceSize() + getObjectExtraSize();176}177178/**179* Calculate approximate size of linked list in memory.180*181* @param length length of list182* @param size size of object183* @return size184*/185public static long getListSize(int length, int size) {186return getObjectExtraSize() + length * (getReferenceSize() + getMemoryObjectSize(size));187}188189/**190* Calculate length of linear or circular linked list.191*192* @param mobj head of list193* @return length of list194*/195public static int getListLength(LinkedMemoryObject mobj) {196LinkedMemoryObject tobj = mobj;197int length = 0;198do {199++length;200tobj = tobj.getNext();201} while (tobj != null && tobj != mobj);202return length;203}204205/**206* Calculate length of array of linear or circular linked lists.207*208* @param mobjs array containting heads of lists209* @return length of all lists210*/211public static int getListsLength(LinkedMemoryObject[] mobjs) {212int length = 0;213for (int i = 0; i < mobjs.length; ++i) {214LinkedMemoryObject mobj = mobjs[i];215if (mobj != null)216length += getListLength(mobj);217}218return length;219}220221/**222* Calculate size of all objects in linear or circular linked list.223*224* @param mobj head of list225* @return size of list226*/227public static long getListSize(LinkedMemoryObject mobj) {228LinkedMemoryObject tobj = mobj;229long size = 0;230do {231size += tobj.getSize();232tobj = tobj.getNext();233} while (tobj != null && tobj != mobj);234return size;235}236237/**238* Calculate size of array of linear or circular linked lists.239*240* @param mobjs array containting heads of lists241* @return size of all lists242*/243public static long getListsSize(LinkedMemoryObject[] mobjs) {244long size = 0;245for (int i = 0; i < mobjs.length; ++i) {246LinkedMemoryObject mobj = mobjs[i];247if (mobj != null)248size += getListSize(mobj);249}250return size;251}252253/**254* Create singly linked linear list of objects of fixed size.255*256* @param depth length of list257* @param size size of each object258* @return head of created list or null if depth = 0259*/260public static LinkedMemoryObject makeLinearList(int depth, int size) {261LinkedMemoryObject mobj = null;262for (int i = 0; i < depth; ++i)263mobj = new LinkedMemoryObject(size, mobj);264return mobj;265}266267/**268* Create singly linked linear list of objects of varying size.269*270* @param depth length of list271* @param size maximum size of each object272* @return head of created list or null if depth = 0273*/274public static LinkedMemoryObject makeRandomLinearList(int depth, int size) {275if (depth == 0)276return null;277LinkedMemoryObject mobj = new LinkedMemoryObject(size);278for (int i = 0; i < depth - 1; ++i)279mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);280return mobj;281}282283/**284* Create singly linked circular linear list of objects of fixed size.285*286* @param depth length of list287* @param size size of each object288* @return head of created list or null if depth = 0289*/290public static LinkedMemoryObject makeCircularList(int depth, int size) {291if (depth == 0)292return null;293LinkedMemoryObject mobj = new LinkedMemoryObject(size);294LinkedMemoryObject tmpobj = mobj;295for (int i = 1; i < depth; i++)296mobj = new LinkedMemoryObject(size, mobj);297tmpobj.setNext(mobj);298return tmpobj;299}300301/**302* Create singly linked circular linear list of objects of varying size.303*304* @param depth length of list305* @param size maximum size of each object306* @return head of created list or null if depth = 0307*/308public static LinkedMemoryObject makeRandomCircularList(int depth, int size) {309if (depth == 0)310return null;311LinkedMemoryObject mobj = new LinkedMemoryObject(size);312LinkedMemoryObject tmpobj = mobj;313for (int i = 0; i < depth - 1; i++)314mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);315tmpobj.setNext(mobj);316return tmpobj;317}318319/**320* Create new nonbranchy binary tree.321*322* Each node in the tree except leaves always has left son. A node323* will have right son with probability branchiness.324*325* @param numberOfNodes number of nodes326* @param branchiness branchiness327* @param size size of each node328* @return root of created tree329*/330public static LinkedMemoryObject makeNonbranchyTree(int numberOfNodes, float branchiness, int size) {331LinkedMemoryObject root = null;332LinkedMemoryObject current = null;333if (numberOfNodes == 0)334return null;335else if (numberOfNodes == 1)336return new LinkedMemoryObject(size);337else if (numberOfNodes == 2)338return new LinkedMemoryObject(size, makeNonbranchyTree(1, branchiness, size));339else {340if (LocalRandom.nextFloat() < branchiness) {341int numberOfLeftNodes = LocalRandom.nextInt(1, numberOfNodes - 1);342int numberOfRightNodes = numberOfNodes - 1 - numberOfLeftNodes;343return new LinkedMemoryObject(344size,345makeNonbranchyTree(numberOfLeftNodes, branchiness, size),346makeNonbranchyTree(numberOfRightNodes, branchiness, size)347);348} else {349return new LinkedMemoryObject(size, makeNonbranchyTree(numberOfNodes - 1, branchiness, size));350}351}352}353354/**355* Create a balanced tree of given height.356*357* @param height height of the tree358* @param size size of each node359* @return created tree360*/361public static Tree makeBalancedTree(int height, long size) {362return new Tree(makeBalancedTreeNode(height, size));363}364365/**366* Get a number of nodes in balanced tree of given height.367*368* @param heigh height of the tree369* @return number of nodes370*/371public static int balancedTreeNodes(int height) {372if (height == 0)373return 0;374int n = 1;375while (height > 1) {376n *= 2;377height--;378}379return n * 2 - 1;380}381382/**383* Get approximate memory size occupied by balanced tree384* of given height and given node size.385*386* @param height height of the tree387* @param nodeSize size of each node388* @return memory size389*/390public static long balancedTreeSize(int height, long nodeSize) {391return balancedTreeNodes(height) * nodeSize;392}393394/**395* Get a height of balanced tree with given number of nodes.396*397* @param nodes number of nodes398* @return height of the tree399*/400public static int balancedTreeHeightFromNodes(int nodes) {401if (nodes == 0)402return 0;403int h = 1;404long n = 1;405while (n + n - 1 <= nodes) {406n = n + n;407h = h + 1;408}409return h - 1;410}411412/**413* Get approximate height of balanced tree which will occupy414* given memory with given node size.415*416* @param memory memory size417* @param nodeSize size of each node418* @return approximate height of the tree419*/420public static int balancedTreeHeightFromMemory(long memory, long nodeSize) {421return balancedTreeHeightFromNodes((int) (memory / nodeSize));422}423424/**425* Create balanced tree of given height and node size.426*427* @param height height of the tree428* @param size size of each node429* @return root of created tree430*/431public static TreeNode makeBalancedTreeNode(int height, long size) {432if (height == 0)433return null;434else435return new TreeNode(size, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));436}437438/**439* Create balanced tree of given height and node size.440*441* @param height height of the tree442* @param size size of each node443* @return root of created tree444*/445public static TreeNode makeBalancedTreeNode(int height, long size, GarbageProducer gp) {446if (height == 0)447return null;448else449return new TreeNode(size, gp, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));450}451452/**453* Determine if given tree is a balanced tree.454*455* @param tree tree456* @return true if tree is balanced457*/458public static boolean isBalancedTree(TreeNode tree) {459return460tree.getActualHeight() == tree.getHeight() &&461tree.getShortestPath() == tree.getHeight();462}463464/**465* Fill an array of MemoryObject's with new objects of given size.466*467* @param array array468* @param count number of objects to create469* @param size size of each object470*/471public static void fillArray(MemoryObject[] array, int count, int size) {472for (int i = 0; i < count; ++i)473array[i] = new MemoryObject(size);474}475476/**477* Fill an array of MemoryObject's with new objects of random size.478*479* @param array array480* @param count number of objects to create481* @param size maximum size of each object482*/483public static void fillArrayRandom(MemoryObject[] array, int count, int size) {484for (int i = 0; i < count; ++i)485array[i] = new MemoryObject(LocalRandom.nextInt(size));486}487488/**489* Fill an array of MemoryObject's with new objects of random size.490*491* @param array array492* @param count number of objects to create493* @param size maximum size of each object494*/495public static void fillArrayRandom(LinkedMemoryObject[] array, int count, int size) {496for (int i = 0; i < count; ++i)497array[i] = new LinkedMemoryObject(LocalRandom.nextInt(size));498}499500public static void dumpStatistics(PrintStream out) {501out.println(Runtime.getRuntime().freeMemory());502out.flush();503}504505public static void dumpStatistics(Log log) {506log.info(Runtime.getRuntime().freeMemory());507}508509public static void dumpStatistics() {510dumpStatistics(System.out);511}512}513514515