8189617: Remove undocumented --print-mem-usage option
Reviewed-by: jlaskey, sundar
This commit is contained in:
parent
3263ea9b0c
commit
7ff7f3b5ab
@ -585,9 +585,6 @@ A short summary follows:
|
||||
-plp, --print-lower-parse (Print the parse tree after lowering.)
|
||||
param: [true|false] default: false
|
||||
|
||||
--print-mem-usage (Print memory usage of IR after each compile stage.)
|
||||
param: [true|false] default: false
|
||||
|
||||
--print-no-newline (Print function will not print new line char.)
|
||||
param: [true|false] default: false
|
||||
|
||||
|
@ -38,7 +38,6 @@ import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
@ -54,8 +53,6 @@ import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.Expression;
|
||||
import jdk.nashorn.internal.ir.FunctionNode;
|
||||
import jdk.nashorn.internal.ir.Optimistic;
|
||||
import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
|
||||
import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
|
||||
import jdk.nashorn.internal.runtime.CodeInstaller;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.ErrorManager;
|
||||
@ -668,10 +665,6 @@ public final class Compiler implements Loggable {
|
||||
|
||||
log.fine(phase, " done for function ", quote(name));
|
||||
|
||||
if (env._print_mem_usage) {
|
||||
printMemoryUsage(functionNode, phase.toString());
|
||||
}
|
||||
|
||||
time += (env.isTimingEnabled() ? phase.getEndTime() - phase.getStartTime() : 0L);
|
||||
}
|
||||
|
||||
@ -846,46 +839,4 @@ public final class Compiler implements Loggable {
|
||||
return invalidatedProgramPoints.get(programPoint);
|
||||
}
|
||||
|
||||
private void printMemoryUsage(final FunctionNode functionNode, final String phaseName) {
|
||||
if (!log.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info(phaseName, "finished. Doing IR size calculation...");
|
||||
|
||||
final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
|
||||
osc.calculateObjectSize(functionNode);
|
||||
|
||||
final List<ClassHistogramElement> list = osc.getClassHistogram();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final long totalSize = osc.calculateObjectSize(functionNode);
|
||||
|
||||
sb.append(phaseName).
|
||||
append(" Total size = ").
|
||||
append(totalSize / 1024 / 1024).
|
||||
append("MB");
|
||||
log.info(sb);
|
||||
|
||||
Collections.sort(list, new Comparator<ClassHistogramElement>() {
|
||||
@Override
|
||||
public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
|
||||
final long diff = o1.getBytes() - o2.getBytes();
|
||||
if (diff < 0) {
|
||||
return 1;
|
||||
} else if (diff > 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
for (final ClassHistogramElement e : list) {
|
||||
final String line = String.format(" %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
|
||||
log.info(line);
|
||||
if (e.getBytes() < totalSize / 200) {
|
||||
log.info(" ...");
|
||||
break; // never mind, so little memory anyway
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 jdk.nashorn.internal.ir.debug;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Class histogram element for IR / Java object instrumentation
|
||||
*/
|
||||
public final class ClassHistogramElement {
|
||||
/**
|
||||
* Instance comparator
|
||||
*/
|
||||
public static final Comparator<ClassHistogramElement> COMPARE_INSTANCES = new Comparator<ClassHistogramElement>() {
|
||||
@Override
|
||||
public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
|
||||
return (int)Math.abs(o1.instances - o2.instances);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bytes comparator
|
||||
*/
|
||||
public static final Comparator<ClassHistogramElement> COMPARE_BYTES = new Comparator<ClassHistogramElement>() {
|
||||
@Override
|
||||
public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
|
||||
return (int)Math.abs(o1.bytes - o2.bytes);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Classname comparator
|
||||
*/
|
||||
public static final Comparator<ClassHistogramElement> COMPARE_CLASSNAMES = new Comparator<ClassHistogramElement>() {
|
||||
@Override
|
||||
public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
|
||||
return o1.clazz.getCanonicalName().compareTo(o2.clazz.getCanonicalName());
|
||||
}
|
||||
};
|
||||
|
||||
private final Class<?> clazz;
|
||||
private long instances;
|
||||
private long bytes;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param clazz class for which to construct histogram
|
||||
*/
|
||||
public ClassHistogramElement(final Class<?> clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an instance
|
||||
* @param sizeInBytes byte count
|
||||
*/
|
||||
public void addInstance(final long sizeInBytes) {
|
||||
instances++;
|
||||
this.bytes += sizeInBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get size in bytes
|
||||
* @return size in bytes
|
||||
*/
|
||||
public long getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class
|
||||
* @return class
|
||||
*/
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of instances
|
||||
* @return number of instances
|
||||
*/
|
||||
public long getInstances() {
|
||||
return instances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ClassHistogramElement[class=" + clazz.getCanonicalName() + ", instances=" + instances + ", bytes=" + bytes + "]";
|
||||
}
|
||||
}
|
@ -1,503 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2016, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 jdk.nashorn.internal.ir.debug;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Contains utility methods for calculating the memory usage of objects. It
|
||||
* only works on the HotSpot JVM, and infers the actual memory layout (32 bit
|
||||
* vs. 64 bit word size, compressed object pointers vs. uncompressed) from
|
||||
* best available indicators. It can reliably detect a 32 bit vs. 64 bit JVM.
|
||||
* It can only make an educated guess at whether compressed OOPs are used,
|
||||
* though; specifically, it knows what the JVM's default choice of OOP
|
||||
* compression would be based on HotSpot version and maximum heap sizes, but if
|
||||
* the choice is explicitly overridden with the <tt>-XX:{+|-}UseCompressedOops</tt> command line
|
||||
* switch, it can not detect
|
||||
* this fact and will report incorrect sizes, as it will presume the default JVM
|
||||
* behavior.
|
||||
*/
|
||||
public final class ObjectSizeCalculator {
|
||||
|
||||
/**
|
||||
* Describes constant memory overheads for various constructs in a JVM implementation.
|
||||
*/
|
||||
public interface MemoryLayoutSpecification {
|
||||
|
||||
/**
|
||||
* Returns the fixed overhead of an array of any type or length in this JVM.
|
||||
*
|
||||
* @return the fixed overhead of an array.
|
||||
*/
|
||||
int getArrayHeaderSize();
|
||||
|
||||
/**
|
||||
* Returns the fixed overhead of for any {@link Object} subclass in this JVM.
|
||||
*
|
||||
* @return the fixed overhead of any object.
|
||||
*/
|
||||
int getObjectHeaderSize();
|
||||
|
||||
/**
|
||||
* Returns the quantum field size for a field owned by an object in this JVM.
|
||||
*
|
||||
* @return the quantum field size for an object.
|
||||
*/
|
||||
int getObjectPadding();
|
||||
|
||||
/**
|
||||
* Returns the fixed size of an object reference in this JVM.
|
||||
*
|
||||
* @return the size of all object references.
|
||||
*/
|
||||
int getReferenceSize();
|
||||
|
||||
/**
|
||||
* Returns the quantum field size for a field owned by one of an object's ancestor superclasses
|
||||
* in this JVM.
|
||||
*
|
||||
* @return the quantum field size for a superclass field.
|
||||
*/
|
||||
int getSuperclassFieldPadding();
|
||||
}
|
||||
|
||||
private static class CurrentLayout {
|
||||
private static final MemoryLayoutSpecification SPEC =
|
||||
getEffectiveMemoryLayoutSpecification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object, returns the total allocated size, in bytes, of the object
|
||||
* and all other objects reachable from it. Attempts to to detect the current JVM memory layout,
|
||||
* but may fail with {@link UnsupportedOperationException};
|
||||
*
|
||||
* @param obj the object; can be null. Passing in a {@link java.lang.Class} object doesn't do
|
||||
* anything special, it measures the size of all objects
|
||||
* reachable through it (which will include its class loader, and by
|
||||
* extension, all other Class objects loaded by
|
||||
* the same loader, and all the parent class loaders). It doesn't provide the
|
||||
* size of the static fields in the JVM class that the Class object
|
||||
* represents.
|
||||
* @return the total allocated size of the object and all other objects it
|
||||
* retains.
|
||||
* @throws UnsupportedOperationException if the current vm memory layout cannot be detected.
|
||||
*/
|
||||
public static long getObjectSize(final Object obj) throws UnsupportedOperationException {
|
||||
return obj == null ? 0 : new ObjectSizeCalculator(CurrentLayout.SPEC).calculateObjectSize(obj);
|
||||
}
|
||||
|
||||
// Fixed object header size for arrays.
|
||||
private final int arrayHeaderSize;
|
||||
// Fixed object header size for non-array objects.
|
||||
private final int objectHeaderSize;
|
||||
// Padding for the object size - if the object size is not an exact multiple
|
||||
// of this, it is padded to the next multiple.
|
||||
private final int objectPadding;
|
||||
// Size of reference (pointer) fields.
|
||||
private final int referenceSize;
|
||||
// Padding for the fields of superclass before fields of subclasses are
|
||||
// added.
|
||||
private final int superclassFieldPadding;
|
||||
|
||||
private final Map<Class<?>, ClassSizeInfo> classSizeInfos = new IdentityHashMap<>();
|
||||
|
||||
|
||||
private final Map<Object, Object> alreadyVisited = new IdentityHashMap<>();
|
||||
private final Map<Class<?>, ClassHistogramElement> histogram = new IdentityHashMap<>();
|
||||
|
||||
private final Deque<Object> pending = new ArrayDeque<>(16 * 1024);
|
||||
private long size;
|
||||
|
||||
/**
|
||||
* Creates an object size calculator that can calculate object sizes for a given
|
||||
* {@code memoryLayoutSpecification}.
|
||||
*
|
||||
* @param memoryLayoutSpecification a description of the JVM memory layout.
|
||||
*/
|
||||
public ObjectSizeCalculator(final MemoryLayoutSpecification memoryLayoutSpecification) {
|
||||
Objects.requireNonNull(memoryLayoutSpecification);
|
||||
arrayHeaderSize = memoryLayoutSpecification.getArrayHeaderSize();
|
||||
objectHeaderSize = memoryLayoutSpecification.getObjectHeaderSize();
|
||||
objectPadding = memoryLayoutSpecification.getObjectPadding();
|
||||
referenceSize = memoryLayoutSpecification.getReferenceSize();
|
||||
superclassFieldPadding = memoryLayoutSpecification.getSuperclassFieldPadding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object, returns the total allocated size, in bytes, of the object
|
||||
* and all other objects reachable from it.
|
||||
*
|
||||
* @param obj the object; can be null. Passing in a {@link java.lang.Class} object doesn't do
|
||||
* anything special, it measures the size of all objects
|
||||
* reachable through it (which will include its class loader, and by
|
||||
* extension, all other Class objects loaded by
|
||||
* the same loader, and all the parent class loaders). It doesn't provide the
|
||||
* size of the static fields in the JVM class that the Class object
|
||||
* represents.
|
||||
* @return the total allocated size of the object and all other objects it
|
||||
* retains.
|
||||
*/
|
||||
public synchronized long calculateObjectSize(final Object obj) {
|
||||
// Breadth-first traversal instead of naive depth-first with recursive
|
||||
// implementation, so we don't blow the stack traversing long linked lists.
|
||||
histogram.clear();
|
||||
try {
|
||||
for (Object o = obj;;) {
|
||||
visit(o);
|
||||
if (pending.isEmpty()) {
|
||||
return size;
|
||||
}
|
||||
o = pending.removeFirst();
|
||||
}
|
||||
} finally {
|
||||
alreadyVisited.clear();
|
||||
pending.clear();
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class histogram
|
||||
* @return class histogram element list
|
||||
*/
|
||||
public List<ClassHistogramElement> getClassHistogram() {
|
||||
return new ArrayList<>(histogram.values());
|
||||
}
|
||||
|
||||
private ClassSizeInfo getClassSizeInfo(final Class<?> clazz) {
|
||||
ClassSizeInfo csi = classSizeInfos.get(clazz);
|
||||
if(csi == null) {
|
||||
csi = new ClassSizeInfo(clazz);
|
||||
classSizeInfos.put(clazz, csi);
|
||||
}
|
||||
return csi;
|
||||
}
|
||||
|
||||
private void visit(final Object obj) {
|
||||
if (alreadyVisited.containsKey(obj)) {
|
||||
return;
|
||||
}
|
||||
final Class<?> clazz = obj.getClass();
|
||||
if (clazz == ArrayElementsVisitor.class) {
|
||||
((ArrayElementsVisitor) obj).visit(this);
|
||||
} else {
|
||||
alreadyVisited.put(obj, obj);
|
||||
if (clazz.isArray()) {
|
||||
visitArray(obj);
|
||||
} else {
|
||||
getClassSizeInfo(clazz).visit(obj, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visitArray(final Object array) {
|
||||
final Class<?> arrayClass = array.getClass();
|
||||
final Class<?> componentType = arrayClass.getComponentType();
|
||||
final int length = Array.getLength(array);
|
||||
if (componentType.isPrimitive()) {
|
||||
increaseByArraySize(arrayClass, length, getPrimitiveFieldSize(componentType));
|
||||
} else {
|
||||
increaseByArraySize(arrayClass, length, referenceSize);
|
||||
// If we didn't use an ArrayElementsVisitor, we would be enqueueing every
|
||||
// element of the array here instead. For large arrays, it would
|
||||
// tremendously enlarge the queue. In essence, we're compressing it into
|
||||
// a small command object instead. This is different than immediately
|
||||
// visiting the elements, as their visiting is scheduled for the end of
|
||||
// the current queue.
|
||||
switch (length) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
enqueue(Array.get(array, 0));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
enqueue(new ArrayElementsVisitor((Object[]) array));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void increaseByArraySize(final Class<?> clazz, final int length, final long elementSize) {
|
||||
increaseSize(clazz, roundTo(arrayHeaderSize + length * elementSize, objectPadding));
|
||||
}
|
||||
|
||||
private static class ArrayElementsVisitor {
|
||||
private final Object[] array;
|
||||
|
||||
ArrayElementsVisitor(final Object[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
public void visit(final ObjectSizeCalculator calc) {
|
||||
for (final Object elem : array) {
|
||||
if (elem != null) {
|
||||
calc.visit(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void enqueue(final Object obj) {
|
||||
if (obj != null) {
|
||||
pending.addLast(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void increaseSize(final Class<?> clazz, final long objectSize) {
|
||||
ClassHistogramElement he = histogram.get(clazz);
|
||||
if(he == null) {
|
||||
he = new ClassHistogramElement(clazz);
|
||||
histogram.put(clazz, he);
|
||||
}
|
||||
he.addInstance(objectSize);
|
||||
size += objectSize;
|
||||
}
|
||||
|
||||
static long roundTo(final long x, final int multiple) {
|
||||
return ((x + multiple - 1) / multiple) * multiple;
|
||||
}
|
||||
|
||||
private class ClassSizeInfo {
|
||||
// Padded fields + header size
|
||||
private final long objectSize;
|
||||
// Only the fields size - used to calculate the subclasses' memory
|
||||
// footprint.
|
||||
private final long fieldsSize;
|
||||
private final Field[] referenceFields;
|
||||
|
||||
public ClassSizeInfo(final Class<?> clazz) {
|
||||
long newFieldsSize = 0;
|
||||
final List<Field> newReferenceFields = new LinkedList<>();
|
||||
for (final Field f : clazz.getDeclaredFields()) {
|
||||
if (Modifier.isStatic(f.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
final Class<?> type = f.getType();
|
||||
if (type.isPrimitive()) {
|
||||
newFieldsSize += getPrimitiveFieldSize(type);
|
||||
} else {
|
||||
f.setAccessible(true);
|
||||
newReferenceFields.add(f);
|
||||
newFieldsSize += referenceSize;
|
||||
}
|
||||
}
|
||||
final Class<?> superClass = clazz.getSuperclass();
|
||||
if (superClass != null) {
|
||||
final ClassSizeInfo superClassInfo = getClassSizeInfo(superClass);
|
||||
newFieldsSize += roundTo(superClassInfo.fieldsSize, superclassFieldPadding);
|
||||
newReferenceFields.addAll(Arrays.asList(superClassInfo.referenceFields));
|
||||
}
|
||||
this.fieldsSize = newFieldsSize;
|
||||
this.objectSize = roundTo(objectHeaderSize + newFieldsSize, objectPadding);
|
||||
this.referenceFields = newReferenceFields.toArray(
|
||||
new Field[0]);
|
||||
}
|
||||
|
||||
void visit(final Object obj, final ObjectSizeCalculator calc) {
|
||||
calc.increaseSize(obj.getClass(), objectSize);
|
||||
enqueueReferencedObjects(obj, calc);
|
||||
}
|
||||
|
||||
public void enqueueReferencedObjects(final Object obj, final ObjectSizeCalculator calc) {
|
||||
for (final Field f : referenceFields) {
|
||||
try {
|
||||
calc.enqueue(f.get(obj));
|
||||
} catch (final IllegalAccessException e) {
|
||||
final AssertionError ae = new AssertionError(
|
||||
"Unexpected denial of access to " + f);
|
||||
ae.initCause(e);
|
||||
throw ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static long getPrimitiveFieldSize(final Class<?> type) {
|
||||
if (type == boolean.class || type == byte.class) {
|
||||
return 1;
|
||||
}
|
||||
if (type == char.class || type == short.class) {
|
||||
return 2;
|
||||
}
|
||||
if (type == int.class || type == float.class) {
|
||||
return 4;
|
||||
}
|
||||
if (type == long.class || type == double.class) {
|
||||
return 8;
|
||||
}
|
||||
throw new AssertionError("Encountered unexpected primitive type " +
|
||||
type.getName());
|
||||
}
|
||||
|
||||
// ALERT: java.lang.management is not available in compact 1. We need
|
||||
// to use reflection to soft link test memory statistics.
|
||||
|
||||
static Class<?> managementFactory = null;
|
||||
static Class<?> memoryPoolMXBean = null;
|
||||
static Class<?> memoryUsage = null;
|
||||
static Method getMemoryPoolMXBeans = null;
|
||||
static Method getUsage = null;
|
||||
static Method getMax = null;
|
||||
static {
|
||||
try {
|
||||
managementFactory = Class.forName("java.lang.management.ManagementFactory");
|
||||
memoryPoolMXBean = Class.forName("java.lang.management.MemoryPoolMXBean");
|
||||
memoryUsage = Class.forName("java.lang.management.MemoryUsage");
|
||||
|
||||
getMemoryPoolMXBeans = managementFactory.getMethod("getMemoryPoolMXBeans");
|
||||
getUsage = memoryPoolMXBean.getMethod("getUsage");
|
||||
getMax = memoryUsage.getMethod("getMax");
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) {
|
||||
// Pass thru, asserts when attempting to use.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current memory usage
|
||||
* @return current memory usage derived from system configuration
|
||||
*/
|
||||
public static MemoryLayoutSpecification getEffectiveMemoryLayoutSpecification() {
|
||||
final String vmName = System.getProperty("java.vm.name");
|
||||
if (vmName == null || !vmName.startsWith("Java HotSpot(TM) ")) {
|
||||
throw new UnsupportedOperationException(
|
||||
"ObjectSizeCalculator only supported on HotSpot VM");
|
||||
}
|
||||
|
||||
final String dataModel = System.getProperty("sun.arch.data.model");
|
||||
if ("32".equals(dataModel)) {
|
||||
// Running with 32-bit data model
|
||||
return new MemoryLayoutSpecification() {
|
||||
@Override public int getArrayHeaderSize() {
|
||||
return 12;
|
||||
}
|
||||
@Override public int getObjectHeaderSize() {
|
||||
return 8;
|
||||
}
|
||||
@Override public int getObjectPadding() {
|
||||
return 8;
|
||||
}
|
||||
@Override public int getReferenceSize() {
|
||||
return 4;
|
||||
}
|
||||
@Override public int getSuperclassFieldPadding() {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
} else if (!"64".equals(dataModel)) {
|
||||
throw new UnsupportedOperationException("Unrecognized value '" +
|
||||
dataModel + "' of sun.arch.data.model system property");
|
||||
}
|
||||
|
||||
final String strVmVersion = System.getProperty("java.vm.version");
|
||||
final int vmVersion = Integer.parseInt(strVmVersion.substring(0,
|
||||
strVmVersion.indexOf('.')));
|
||||
if (vmVersion >= 17) {
|
||||
long maxMemory = 0;
|
||||
|
||||
/*
|
||||
See ALERT above. The reflection code below duplicates the following
|
||||
sequence, and avoids hard coding of java.lang.management.
|
||||
|
||||
for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) {
|
||||
maxMemory += mp.getUsage().getMax();
|
||||
}
|
||||
*/
|
||||
|
||||
if (getMemoryPoolMXBeans == null) {
|
||||
throw new AssertionError("java.lang.management not available in compact 1");
|
||||
}
|
||||
|
||||
try {
|
||||
final List<?> memoryPoolMXBeans = (List<?>)getMemoryPoolMXBeans.invoke(managementFactory);
|
||||
for (final Object mp : memoryPoolMXBeans) {
|
||||
final Object usage = getUsage.invoke(mp);
|
||||
final Object max = getMax.invoke(usage);
|
||||
maxMemory += ((Long)max);
|
||||
}
|
||||
} catch (IllegalAccessException |
|
||||
IllegalArgumentException |
|
||||
InvocationTargetException ex) {
|
||||
throw new AssertionError("java.lang.management not available in compact 1");
|
||||
}
|
||||
|
||||
if (maxMemory < 30L * 1024 * 1024 * 1024) {
|
||||
// HotSpot 17.0 and above use compressed OOPs below 30GB of RAM total
|
||||
// for all memory pools (yes, including code cache).
|
||||
return new MemoryLayoutSpecification() {
|
||||
@Override public int getArrayHeaderSize() {
|
||||
return 16;
|
||||
}
|
||||
@Override public int getObjectHeaderSize() {
|
||||
return 12;
|
||||
}
|
||||
@Override public int getObjectPadding() {
|
||||
return 8;
|
||||
}
|
||||
@Override public int getReferenceSize() {
|
||||
return 4;
|
||||
}
|
||||
@Override public int getSuperclassFieldPadding() {
|
||||
return 4;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// In other cases, it's a 64-bit uncompressed OOPs object model
|
||||
return new MemoryLayoutSpecification() {
|
||||
@Override public int getArrayHeaderSize() {
|
||||
return 24;
|
||||
}
|
||||
@Override public int getObjectHeaderSize() {
|
||||
return 16;
|
||||
}
|
||||
@Override public int getObjectPadding() {
|
||||
return 8;
|
||||
}
|
||||
@Override public int getReferenceSize() {
|
||||
return 8;
|
||||
}
|
||||
@Override public int getSuperclassFieldPadding() {
|
||||
return 8;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -189,9 +189,6 @@ public final class ScriptEnvironment {
|
||||
/** List of functions to write to the print code dir, optional */
|
||||
public final String _print_code_func;
|
||||
|
||||
/** Print memory usage for IR after each phase */
|
||||
public final boolean _print_mem_usage;
|
||||
|
||||
/** Print function will no print newline characters */
|
||||
public final boolean _print_no_newline;
|
||||
|
||||
@ -301,7 +298,6 @@ public final class ScriptEnvironment {
|
||||
_print_ast = options.getBoolean("print.ast");
|
||||
_print_lower_ast = options.getBoolean("print.lower.ast");
|
||||
_print_code = options.getString("print.code") != null;
|
||||
_print_mem_usage = options.getBoolean("print.mem.usage");
|
||||
_print_no_newline = options.getBoolean("print.no.newline");
|
||||
_print_parse = options.getBoolean("print.parse");
|
||||
_print_lower_parse = options.getBoolean("print.lower.parse");
|
||||
|
@ -325,12 +325,6 @@ nashorn.option.print.code = { \
|
||||
desc="Print generated bytecode. If a directory is specified, nothing will be dumped to stderr. Also, in that case, .dot files will be generated for all functions or for the function with the specified name only." \
|
||||
}
|
||||
|
||||
nashorn.option.print.mem.usage = { \
|
||||
name="--print-mem-usage", \
|
||||
is_undocumented=true, \
|
||||
desc="Print memory usage of IR after each compile stage." \
|
||||
}
|
||||
|
||||
nashorn.option.print.no.newline = { \
|
||||
name="--print-no-newline", \
|
||||
is_undocumented=true, \
|
||||
|
Loading…
Reference in New Issue
Block a user