Mercurial > hg > truffle
changeset 15581:0dc0926cf0d8
added -G:TrackMemUse for measuring memory usage within scopes
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java Fri May 09 17:59:15 2014 +0200 @@ -384,7 +384,7 @@ public StructuredGraph visualize(StructuredGraph graph, String title) { DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, false, debugConfig.dumpHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { Debug.dump(graph, title);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri May 09 17:59:15 2014 +0200 @@ -42,6 +42,8 @@ public static final OptionValue<String> Dump = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)") public static final OptionValue<String> Meter = new OptionValue<>(null); + @Option(help = "Pattern for scope(s) to in which memory use tracking is enabled (see DebugFilter and Debug.metric)") + public static final OptionValue<String> TrackMemUse = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which timing is enabled (see DebugFilter and Debug.timer)") public static final OptionValue<String> Time = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which logging is enabled (see DebugFilter and Debug.log)") @@ -79,11 +81,12 @@ } public static boolean areMetricsOrTimersEnabled() { - return Meter.getValue() != null || Time.getValue() != null; + return Meter.getValue() != null || Time.getValue() != null || TrackMemUse.getValue() != null; } private final DebugFilter logFilter; private final DebugFilter meterFilter; + private final DebugFilter trackMemUseFilter; private final DebugFilter timerFilter; private final DebugFilter dumpFilter; private final MethodFilter[] methodFilter; @@ -91,9 +94,11 @@ private final PrintStream output; private final Set<Object> extraFilters = new HashSet<>(); - public GraalDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output, List<DebugDumpHandler> dumpHandlers) { + public GraalDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output, + List<DebugDumpHandler> dumpHandlers) { this.logFilter = DebugFilter.parse(logFilter); this.meterFilter = DebugFilter.parse(meterFilter); + this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); this.timerFilter = DebugFilter.parse(timerFilter); this.dumpFilter = DebugFilter.parse(dumpFilter); if (methodFilter == null || methodFilter.isEmpty()) { @@ -122,6 +127,14 @@ return isEnabled(meterFilter); } + public boolean isMetderEnabled() { + return isEnabled(meterFilter); + } + + public boolean isMemUseTrackingEnabled() { + return isEnabled(trackMemUseFilter); + } + public boolean isDumpEnabled() { return isEnabled(dumpFilter); } @@ -218,7 +231,7 @@ if (e instanceof BailoutException) { return null; } - Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers, output)); + Debug.setConfig(Debug.fixedConfig(true, true, false, false, false, dumpHandlers, output)); Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) { if (o instanceof Graph) {
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri May 09 17:59:15 2014 +0200 @@ -94,6 +94,10 @@ return ENABLED && DebugScope.getInstance().isTimeEnabled(); } + public static boolean isMemUseTrackingEnabled() { + return ENABLED && DebugScope.getInstance().isMemUseTrackingEnabled(); + } + public static boolean isLogEnabledForMethod() { if (!ENABLED) { return false; @@ -586,6 +590,69 @@ } /** + * Creates a {@linkplain DebugMemUseTracker memory use tracker} that is enabled iff debugging is + * {@linkplain #isEnabled() enabled}. + * <p> + * A disabled tracker has virtually no overhead. + */ + public static DebugMemUseTracker memUseTracker(CharSequence name) { + if (!ENABLED) { + return VOID_MEM_USE_TRACKER; + } + return createMemUseTracker("%s", name, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + * <pre> + * Debug.memUseTracker(format, arg, null) + * </pre> + * + * except that the string formatting only happens if metering is enabled. + * + * @see #metric(String, Object, Object) + */ + public static DebugMemUseTracker memUseTracker(String format, Object arg) { + if (!ENABLED) { + return VOID_MEM_USE_TRACKER; + } + return createMemUseTracker(format, arg, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + * <pre> + * Debug.memUseTracker(String.format(format, arg1, arg2)) + * </pre> + * + * except that the string formatting only happens if memory use tracking is enabled. In + * addition, each argument is subject to the following type based conversion before being passed + * as an argument to {@link String#format(String, Object...)}: + * + * <pre> + * Type | Conversion + * ------------------+----------------- + * java.lang.Class | arg.getSimpleName() + * | + * </pre> + * + * @see #memUseTracker(CharSequence) + */ + public static DebugMemUseTracker memUseTracker(String format, Object arg1, Object arg2) { + if (!ENABLED) { + return VOID_MEM_USE_TRACKER; + } + return createMemUseTracker(format, arg1, arg2); + } + + private static DebugMemUseTracker createMemUseTracker(String format, Object arg1, Object arg2) { + String name = formatDebugName(format, arg1, arg2); + return new MemUseTrackerImpl(name); + } + + /** * Creates a {@linkplain DebugMetric metric} that is enabled iff debugging is * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding to * {@value #ENABLE_METRIC_PROPERTY_NAME_PREFIX} to {@code name} is @@ -702,10 +769,10 @@ } public static DebugConfig silentConfig() { - return fixedConfig(false, false, false, false, Collections.<DebugDumpHandler> emptyList(), System.out); + return fixedConfig(false, false, false, false, false, Collections.<DebugDumpHandler> emptyList(), System.out); } - public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled, final Collection<DebugDumpHandler> dumpHandlers, final PrintStream output) { return new DebugConfig() { @@ -724,6 +791,11 @@ } @Override + public boolean isMemUseTrackingEnabled() { + return isMemUseTrackingEnabled; + } + + @Override public boolean isDumpEnabled() { return isDumpEnabled; } @@ -783,6 +855,17 @@ } }; + private static final DebugMemUseTracker VOID_MEM_USE_TRACKER = new DebugMemUseTracker() { + + public Closeable start() { + return MemUseTrackerImpl.VOID_CLOSEABLE; + } + + public long getCurrentValue() { + return 0; + } + }; + /** * @see #timer(CharSequence) */ @@ -875,7 +958,19 @@ public static Object convertFormatArg(Object arg) { if (arg instanceof Class) { - return ((Class<?>) arg).getSimpleName(); + Class<?> c = (Class<?>) arg; + final String simpleName = c.getSimpleName(); + Class<?> enclosingClass = c.getEnclosingClass(); + if (enclosingClass != null) { + String prefix = ""; + while (enclosingClass != null) { + prefix = enclosingClass.getSimpleName() + "_" + prefix; + enclosingClass = enclosingClass.getEnclosingClass(); + } + return prefix + simpleName; + } else { + return simpleName; + } } return arg; }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Fri May 09 17:59:15 2014 +0200 @@ -47,6 +47,14 @@ boolean isMeterEnabled(); /** + * Determines if memory use tracking is enabled in the {@linkplain Debug#currentScope() current + * debug scope}. + * + * @see Debug#memUseTracker(CharSequence) + */ + boolean isMemUseTrackingEnabled(); + + /** * Determines if dumping is enabled in the {@linkplain Debug#currentScope() current debug scope} * . *
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMemUseTracker.java Fri May 09 17:59:15 2014 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 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 com.oracle.graal.debug; + +import com.sun.management.*; + +/** + * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed + * using the try-with-resources pattern: + * + * <pre> + * try (DebugMemUseTracker.Closeable a = memUseTracker.start()) { + * // the code to measure + * } + * </pre> + */ +public interface DebugMemUseTracker { + + public interface Closeable extends AutoCloseable { + void close(); + } + + /** + * Creates a point from which memory usage will be recorded if memory use tracking is + * {@linkplain Debug#isMemUseTrackingEnabled() enabled}. + * + * @return an object that must be closed once the activity has completed to add the memory used + * since this call to the total for this tracker + */ + Closeable start(); + + /** + * Gets the current value of this tracker. + */ + long getCurrentValue(); +}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java Fri May 09 17:59:15 2014 +0200 @@ -29,7 +29,7 @@ /** * A timer for some activity of interest. A timer should be deployed using the try-with-resources * pattern: - * + * * <pre> * try (TimerCloseable a = timer.start()) { * // the code to time @@ -41,21 +41,20 @@ /** * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an * {@linkplain #isConditional() unconditional} timer. - * + * * @return an object that must be closed once the activity has completed to add the elapsed time * since this call to the total for this timer */ TimerCloseable start(); /** - * Sets a flag determining if this timer is only enabled if metering is - * {@link Debug#isMeterEnabled() enabled}. + * Sets a flag determining if this timer is only enabled if timing is + * {@link Debug#isTimeEnabled() enabled}. */ void setConditional(boolean flag); /** - * Determines if this timer is only enabled if metering is {@link Debug#isMeterEnabled() - * enabled}. + * Determines if this timer is only enabled if timing is {@link Debug#isTimeEnabled() enabled}. */ boolean isConditional();
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DelegatingDebugConfig.java Fri May 09 17:59:15 2014 +0200 @@ -59,6 +59,10 @@ */ METER, /** + * @see Debug#isMemUseTrackingEnabled() + */ + TRACK_MEM_USE, + /** * @see Debug#isTimeEnabled() */ TIME, @@ -125,6 +129,14 @@ return fs.booleanValue(); } + public boolean isMemUseTrackingEnabled() { + Boolean fs = featureState.get(Feature.TRACK_MEM_USE); + if (fs == null) { + return delegate.isMemUseTrackingEnabled(); + } + return fs.booleanValue(); + } + @Override public boolean isDumpEnabled() { Boolean fs = featureState.get(Feature.DUMP);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Fri May 09 17:59:15 2014 +0200 @@ -93,6 +93,7 @@ private boolean meterEnabled; private boolean timeEnabled; + private boolean memUseTrackingEnabled; private boolean dumpEnabled; private boolean logEnabled; @@ -169,6 +170,10 @@ return timeEnabled; } + public boolean isMemUseTrackingEnabled() { + return memUseTrackingEnabled; + } + public void log(String msg, Object... args) { lastUsedIndent.log(msg, args); } @@ -261,6 +266,7 @@ DebugConfig config = getConfig(); if (config == null) { meterEnabled = false; + memUseTrackingEnabled = false; timeEnabled = false; dumpEnabled = false; @@ -269,6 +275,7 @@ output = System.out; } else { meterEnabled = config.isMeterEnabled(); + memUseTrackingEnabled = config.isMemUseTrackingEnabled(); timeEnabled = config.isTimeEnabled(); dumpEnabled = config.isDumpEnabled(); logEnabled = config.isLogEnabled();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MemUseTrackerImpl.java Fri May 09 17:59:15 2014 +0200 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2012, 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 com.oracle.graal.debug.internal; + +import java.lang.management.*; + +import com.oracle.graal.debug.*; +import com.sun.management.ThreadMXBean; + +public final class MemUseTrackerImpl extends DebugValue implements DebugMemUseTracker { + + private static final ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); + + public static final Closeable VOID_CLOSEABLE = new Closeable() { + + @Override + public void close() { + } + }; + + /** + * Records the most recent active tracker. + */ + private static final ThreadLocal<CloseableImpl> currentTracker = new ThreadLocal<>(); + + private final DebugValue flat; + + public MemUseTrackerImpl(String name) { + super(name + "_Accm", false); + this.flat = new DebugValue(name + "_Flat", false) { + + @Override + public String toString(long value) { + return valueToString(value); + } + }; + } + + @Override + public Closeable start() { + if (!isConditional() || Debug.isTimeEnabled()) { + CloseableImpl result = new CloseableImpl(); + currentTracker.set(result); + return result; + } else { + return VOID_CLOSEABLE; + } + } + + public static String valueToString(long value) { + return String.format("%d bytes", value); + } + + @Override + public String toString(long value) { + return valueToString(value); + } + + private final class CloseableImpl implements Closeable { + + private final CloseableImpl parent; + private final long start; + private long nestedAmountToSubtract; + + private CloseableImpl() { + this.parent = currentTracker.get(); + this.start = threadMXBean.getThreadAllocatedBytes(Thread.currentThread().getId()); + } + + @Override + public void close() { + long end = threadMXBean.getThreadAllocatedBytes(Thread.currentThread().getId()); + long allocated = end - start; + if (parent != null) { + parent.nestedAmountToSubtract += allocated; + } + currentTracker.set(parent); + MemUseTrackerImpl.this.addToCurrentValue(allocated); + flat.addToCurrentValue(allocated - nestedAmountToSubtract); + } + } +}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Fri May 09 17:59:15 2014 +0200 @@ -692,7 +692,7 @@ }; DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, debugConfig.dumpHandlers(), debugConfig.output()); + DebugConfig fixedConfig = Debug.fixedConfig(false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.output()); try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase().apply(graph);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Fri May 09 17:59:15 2014 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.debug.DebugMemUseTracker.Closeable; import com.oracle.graal.debug.internal.*; import com.oracle.graal.nodes.*; @@ -40,6 +41,7 @@ private final DebugTimer phaseTimer; private final DebugMetric phaseMetric; + private final DebugMemUseTracker phaseMemUseTracker; private static final Pattern NAME_PATTERN = Pattern.compile("[A-Z][A-Za-z0-9]+"); @@ -51,6 +53,7 @@ protected BasePhase() { phaseTimer = Debug.timer("PhaseTime_%s", getClass()); phaseMetric = Debug.metric("PhaseCount_%s", getClass()); + phaseMemUseTracker = Debug.memUseTracker("PhaseMemUse_%s", getClass()); } protected BasePhase(String name) { @@ -58,6 +61,7 @@ this.name = name; phaseTimer = Debug.timer("PhaseTime_%s", getClass()); phaseMetric = Debug.metric("PhaseCount_%s", getClass()); + phaseMemUseTracker = Debug.memUseTracker("PhaseMemUse_%s", getClass()); } protected CharSequence getDetailedName() { @@ -69,7 +73,7 @@ } public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { - try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(getClass(), this)) { + try (TimerCloseable a = phaseTimer.start(); Scope s = Debug.scope(getClass(), this); Closeable c = phaseMemUseTracker.start()) { BasePhase.this.run(graph, context); phaseMetric.increment(); if (dumpGraph && Debug.isDumpEnabled()) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Fri May 09 16:43:26 2014 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Fri May 09 17:59:15 2014 +0200 @@ -49,7 +49,7 @@ if (DecompileAfterPhase.getValue() != null) { dumpHandlers.add(new DecompilerDebugDumpHandler()); } - GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers); + GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers); Debug.setConfig(debugConfig); return debugConfig; }