Skip to content
Snippets Groups Projects
Commit aac97a79 authored by Stepan Sindelar's avatar Stepan Sindelar
Browse files

[GR-2738] Remove obsolete FastR specific profiling.

PullRequest: fastr/1323
parents df0d2403 ffa8a811
No related branches found
No related tags found
No related merge requests found
......@@ -120,10 +120,6 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfo;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfoNodeGen;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTrace;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfFuncounts;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfTypecounts;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRStatsFactory;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRSyntaxTree;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRSyntaxTreeNodeGen;
import com.oracle.truffle.r.nodes.builtin.fastr.FastRThrowIt;
......@@ -465,9 +461,6 @@ public class BasePackage extends RBuiltinPackage {
add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
add(FastRSourceInfo.class, FastRSourceInfoNodeGen::create);
add(FastRStackTrace.class, FastRStackTraceNodeGen::create);
add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create);
add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create);
add(FastRProfFuncounts.class, FastRStatsFactory.FastRProfFuncountsNodeGen::create);
add(FastRSlotAssign.class, FastRSlotAssignNodeGen::create);
add(FastRSyntaxTree.class, FastRSyntaxTreeNodeGen::create);
add(FastRThrowIt.class, FastRThrowItNodeGen::create);
......
/*
* Copyright (c) 2016, 2017, 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.truffle.r.nodes.builtin.fastr;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
import static com.oracle.truffle.r.runtime.RVisibility.OFF;
import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.RSource;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.r.runtime.data.AttributeTracer;
import com.oracle.truffle.r.runtime.data.AttributeTracer.Change;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RTypedValue;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
import com.oracle.truffle.r.runtime.instrument.InstrumentationState.RprofState;
import com.oracle.truffle.tools.Profiler;
import com.oracle.truffle.tools.Profiler.Counter.TimeKind;
public class FastRStats {
private static final class CastsHelper {
private static void filename(Casts casts) {
casts.arg("filename").allowNull().mustBe(stringValue()).asStringVector();
}
private static void append(Casts casts) {
casts.arg("append").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
}
}
@RBuiltin(name = ".fastr.prof.attr", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX)
public abstract static class FastRProfAttr extends RBuiltinNode.Arg2 implements AttributeTracer.Listener {
@Override
public Object[] getDefaultParameterValues() {
return new Object[]{"Rprofattr.out", RRuntime.LOGICAL_FALSE};
}
static {
Casts casts = new Casts(FastRProfAttr.class);
CastsHelper.filename(casts);
CastsHelper.append(casts);
}
@SuppressWarnings("unused")
@Specialization
@TruffleBoundary
protected RNull profAttr(RNull filenameVec, boolean append) {
endProfiling();
return RNull.instance;
}
@Specialization
@TruffleBoundary
protected RNull profAttr(RAbstractStringVector filenameVec, boolean append) {
if (filenameVec.getLength() == 0) {
// disable
endProfiling();
} else {
// enable after ending any previous session
State state = State.get();
try {
PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append));
state.setOut(out);
AttributeTracer.addListener(this);
AttributeTracer.setTracingState(true);
} catch (IOException ex) {
throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
}
}
return RNull.instance;
}
protected void endProfiling() {
State state = State.get();
if (state.out() != null) {
state.cleanup(0);
}
}
@Override
public void reportAttributeChange(Change change, DynamicObject attrs, Object value) {
State rprofattrState = State.get();
rprofattrState.out().printf("%s,%d,", change.name(), System.identityHashCode(attrs));
switch (change) {
case CREATE:
rprofattrState.out().print("NA");
break;
case GROW:
rprofattrState.out().printf("%d", (int) value);
break;
default:
rprofattrState.out().printf("%s", (String) value);
break;
}
rprofattrState.out().println();
}
private static class State extends RprofState {
private static State get() {
State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("attr");
if (state == null) {
state = new State();
RContext.getInstance().stateInstrumentation.setRprofState("attr", state);
}
return state;
}
@Override
public void cleanup(int status) {
AttributeTracer.setTracingState(false);
closeAndResetOut();
}
}
}
@RBuiltin(name = ".fastr.stats.typecounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX)
public abstract static class FastRProfTypecounts extends RBuiltinNode.Arg2 {
@Override
public Object[] getDefaultParameterValues() {
return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE};
}
static {
Casts casts = new Casts(FastRProfTypecounts.class);
CastsHelper.filename(casts);
CastsHelper.append(casts);
}
@SuppressWarnings("unused")
@Specialization
@TruffleBoundary
protected RNull profTypecounts(RNull filenameVec, boolean append) {
endProfiling();
return RNull.instance;
}
@Specialization
@TruffleBoundary
protected RNull profTypecounts(RAbstractStringVector filenameVec, boolean append) {
if (filenameVec.getLength() == 0) {
// disable
endProfiling();
} else {
// enable after ending any previous session
State state = State.get();
try {
PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append));
state.setOut(out);
RDataFactory.addListener(LISTENER);
} catch (IOException ex) {
throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
}
}
return RNull.instance;
}
protected void endProfiling() {
State state = State.get();
if (state.out() != null) {
RDataFactory.removeListener(LISTENER);
state.cleanup(0);
}
}
private static final RDataFactory.Listener LISTENER = new RDataFactory.Listener() {
@Override
public void reportAllocation(RTypedValue data) {
Class<? extends RTypedValue> klass = data.getClass();
boolean isVector = (data instanceof RAbstractVector);
State state = State.get();
Map<Class<? extends RTypedValue>, SortedMap<Integer, State.Counter>> typecountsMap = state.getTypecountsMap();
SortedMap<Integer, State.Counter> countsMap = typecountsMap.get(klass);
if (countsMap == null) {
countsMap = new TreeMap<>();
typecountsMap.put(klass, countsMap);
}
int length;
if (isVector) {
RAbstractVector vector = (RAbstractVector) data;
length = vector.getLength();
} else {
length = 1;
}
State.Counter count = countsMap.get(length);
if (count == null) {
count = new State.Counter();
countsMap.put(length, count);
}
count.incCount();
}
};
private static class State extends RprofState {
public static class Counter {
private int count;
public void incCount() {
count++;
}
public int getCount() {
return count;
}
@Override
public String toString() {
return Integer.toString(count);
}
}
private Map<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> typecountsMap;
private static State get() {
State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("typecounts");
if (state == null) {
state = new State();
RContext.getInstance().stateInstrumentation.setRprofState("typecounts", state);
}
return state;
}
private Map<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> getTypecountsMap() {
if (typecountsMap == null) {
typecountsMap = new HashMap<>();
}
return typecountsMap;
}
@Override
public void cleanup(int status) {
for (Map.Entry<Class<? extends RTypedValue>, SortedMap<Integer, Counter>> entry : getTypecountsMap().entrySet()) {
SortedMap<Integer, Counter> countsMap = entry.getValue();
int totalCount = 0;
for (Counter counter : countsMap.values()) {
totalCount += counter.getCount();
}
out().printf("%s,%d", entry.getKey().getSimpleName(), totalCount);
for (Map.Entry<Integer, Counter> countsEntry : countsMap.entrySet()) {
out().printf(",%d:%d", countsEntry.getKey(), countsEntry.getValue().getCount());
}
out().println();
}
closeAndResetOut();
}
}
}
@RBuiltin(name = ".fastr.stats.funcounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append", "timing", "threshold", "histograms"}, behavior = COMPLEX)
public abstract static class FastRProfFuncounts extends RBuiltinNode.Arg5 {
@Override
public Object[] getDefaultParameterValues() {
return new Object[]{"Rproffuncounts.out", RRuntime.LOGICAL_FALSE, RRuntime.LOGICAL_FALSE, 0, RRuntime.LOGICAL_FALSE};
}
static {
Casts casts = new Casts(FastRProfFuncounts.class);
CastsHelper.filename(casts);
CastsHelper.append(casts);
casts.arg("timing").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
casts.arg("threshold").asIntegerVector().findFirst().mustNotBeNA();
casts.arg("histograms").asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
}
@SuppressWarnings("unused")
@Specialization
@TruffleBoundary
protected RNull profFuncounts(RNull filenameVec, boolean append, boolean timing, int threshold, boolean histograms) {
endProfiling();
return RNull.instance;
}
@Specialization
@TruffleBoundary
protected RNull profFuncounts(RAbstractStringVector filenameVec, boolean append, boolean timing, int threshold, boolean histograms) {
if (filenameVec.getLength() == 0) {
// disable
endProfiling();
} else {
// enable after ending any previous session
State state = State.get();
try {
PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append));
state.initialize(out, threshold, timing, histograms);
Profiler profiler = RContext.getInstance().stateInstrumentation.getProfiler();
profiler.setCollecting(true);
profiler.setTiming(timing);
} catch (IOException ex) {
throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
}
}
return RNull.instance;
}
protected void endProfiling() {
State state = State.get();
if (state.out() != null) {
state.cleanup(0);
}
}
private static class State extends RprofState {
private int threshold;
private boolean timing;
private boolean histograms;
private static State get() {
State state = (State) RContext.getInstance().stateInstrumentation.getRprofState("funcounts");
if (state == null) {
state = new State();
RContext.getInstance().stateInstrumentation.setRprofState("funcounts", state);
}
return state;
}
private void initialize(PrintStream outA, int thresholdA, boolean timingA, boolean histogramsA) {
this.setOut(outA);
this.threshold = thresholdA;
this.timing = timingA;
this.histograms = histogramsA;
}
@Override
public void cleanup(int status) {
Profiler profiler = RContext.getInstance().getInstrumentationState().getProfiler();
if (histograms) {
profiler.printHistograms(out());
return;
}
/*
* Report the statement counts/timing information at the end of the run. The report
* is per function. If timing is on, output is sorted by time, otherwise by
* invocation count. When timing, functions that consumed less time than requested
* threshold (default 0) are not included in the report.
*/
Map<SourceSection, Profiler.Counter> counters = profiler.getCounters();
long totalTime = 0;
SortableCounter[] sortedCounters = new SortableCounter[counters.size()];
int i = 0;
for (Profiler.Counter counter : counters.values()) {
sortedCounters[i++] = new SortableCounter(counter, timing);
if (timing) {
totalTime += counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED);
}
}
Arrays.sort(sortedCounters);
for (SortableCounter scounter : sortedCounters) {
long time = scounter.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED);
long invocations = scounter.counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED);
boolean include = timing ? time > 0 && time > threshold : invocations > 0;
if (include) {
SourceSection ss = scounter.counter.getSourceSection();
Source source = ss.getSource();
out().println("==========");
out().printf("calls %d", invocations);
if (timing) {
double thisPercent = percent(time, totalTime);
out().printf(", time %d ms (%.2f%%)", time, thisPercent);
}
out().printf(": %s, %s%n", scounter.counter.getName(), RSource.getOrigin(source));
}
}
profiler.clearData();
closeAndResetOut();
}
private static double percent(long a, long b) {
return ((double) a * 100) / b;
}
}
private static final class SortableCounter implements Comparable<SortableCounter> {
private final boolean timing;
private final Profiler.Counter counter;
private SortableCounter(Profiler.Counter counter, boolean timing) {
this.counter = counter;
this.timing = timing;
}
@Override
public int compareTo(SortableCounter other) {
if (timing) {
long myTime = counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED);
long otherTime = other.counter.getSelfTime(TimeKind.INTERPRETED_AND_COMPILED);
return myTime < otherTime ? 1 : (myTime > otherTime ? -1 : 0);
} else {
long myInvocations = counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED);
long otherInvocations = other.counter.getInvocations(TimeKind.INTERPRETED_AND_COMPILED);
return myInvocations < otherInvocations ? 1 : (myInvocations > otherInvocations ? -1 : 0);
}
}
}
}
}
......@@ -35,11 +35,9 @@ import com.oracle.truffle.api.instrumentation.EventBinding;
import com.oracle.truffle.api.instrumentation.ExecutionEventListener;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.vm.PolyglotEngine;
import com.oracle.truffle.r.runtime.RCaller;
import com.oracle.truffle.r.runtime.RCleanUp;
import com.oracle.truffle.r.runtime.context.RContext;
import com.oracle.truffle.tools.Profiler;
/**
* Collects together all the context-specific state related to profiling, instrumentation.
......@@ -64,11 +62,6 @@ public final class InstrumentationState implements RContext.ContextState {
*/
private final Instrumenter instrumenter;
/**
* The {@link Profiler}, if any, associated with this {@link RContext}.
*/
private Profiler profiler;
private TracememContext tracememContext;
Map<String, RprofState> rprofStates = new ConcurrentHashMap<>(7);
......@@ -236,14 +229,6 @@ public final class InstrumentationState implements RContext.ContextState {
return tracingState;
}
public Profiler getProfiler() {
if (profiler == null) {
PolyglotEngine vm = RContext.getInstance().getVM();
profiler = Profiler.find(vm);
}
return profiler;
}
public Instrumenter getInstrumenter() {
return instrumenter;
}
......
......@@ -7,7 +7,7 @@ suite = {
{
"name" : "truffle",
"subdir" : True,
"version" : "b1c4af13e75d2dc839b5050ba020356ec1602788",
"version" : "e140680ae7ebc4329e5cd96889258a75b6987dfe",
"urls" : [
{"url" : "https://github.com/graalvm/graal", "kind" : "git"},
{"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
......@@ -114,7 +114,6 @@ suite = {
"sourceDirs" : ["src"],
"dependencies" : [
"com.oracle.truffle.r.runtime",
"truffle:TRUFFLE_DEBUG",
],
"checkstyle" : "com.oracle.truffle.r.runtime",
"javaCompliance" : "1.8",
......@@ -197,7 +196,6 @@ suite = {
"com.oracle.truffle.r.nodes.builtin",
"com.oracle.truffle.r.parser",
"truffle:JLINE",
"truffle:TRUFFLE_DEBUG",
"truffle:TRUFFLE_NFI",
],
"generatedDependencies" : [
......@@ -218,7 +216,6 @@ suite = {
"dependencies" : [
"com.oracle.truffle.r.launcher",
"truffle:TRUFFLE_API",
"truffle:TRUFFLE_DEBUG",
"XZ-1.6",
],
"checkstyle" : "com.oracle.truffle.r.runtime",
......@@ -358,7 +355,6 @@ suite = {
],
"distDependencies" : [
"truffle:TRUFFLE_API",
"truffle:TRUFFLE_DEBUG",
"truffle:TRUFFLE_NFI",
"truffle:TRUFFLE_NFI_NATIVE",
],
......@@ -374,7 +370,6 @@ suite = {
"distDependencies" : [
"FASTR",
"truffle:TRUFFLE_API",
"truffle:TRUFFLE_DEBUG",
"TRUFFLE_R_PARSER_PROCESSOR",
"truffle:TRUFFLE_TCK",
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment