Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inline compilation benchmarks and Improve searching Graph.Link performance #9520

Merged
merged 7 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.enso.compiler.Compiler;
import org.enso.compiler.benchmarks.Utils;
import org.enso.compiler.context.InlineContext;
import org.graalvm.polyglot.Context;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
Expand Down Expand Up @@ -46,19 +46,18 @@ public class InlineCompilerBenchmark {
private final OutputStream out = new ByteArrayOutputStream();
private Compiler compiler;
private Context ctx;
private InlineContext mainInlineContext;
private InlineSource inlineSource;
private String longExpression;
private Set<String> localVarNames;

@Setup
public void setup() throws IOException {
ctx = Utils.createDefaultContextBuilder().out(out).err(out).logHandler(out).build();
var ensoCtx = Utils.leakEnsoContext(ctx);
compiler = ensoCtx.getCompiler();

var inlineSource = InlineContextUtils.createMainMethodWithLocalVars(ctx, LOCAL_VARS_CNT);
mainInlineContext = inlineSource.mainInlineContext();
longExpression =
InlineContextUtils.createLongExpression(inlineSource.localVarNames(), LONG_EXPR_SIZE);
localVarNames = InlineContextUtils.localVarNames(LOCAL_VARS_CNT);
longExpression = InlineContextUtils.createLongExpression(localVarNames, LONG_EXPR_SIZE);
inlineSource = InlineContextUtils.createMainMethodWithLocalVars(ctx, localVarNames);
}

@TearDown
Expand All @@ -75,11 +74,13 @@ public void tearDown() {
}

@Benchmark
public void longExpression(Blackhole blackhole) {
var tuppleOpt = compiler.runInline(longExpression, mainInlineContext);
if (tuppleOpt.isEmpty()) {
throw new AssertionError("Unexpected: inline compilation should succeed");
public void longExpression(Blackhole blackhole) throws IOException {
try (InlineContextResource resource = inlineSource.builder().build()) {
var tuppleOpt = compiler.runInline(longExpression, resource.inlineContext());
if (tuppleOpt.isEmpty()) {
throw new AssertionError("Unexpected: inline compilation should succeed");
}
blackhole.consume(tuppleOpt);
}
blackhole.consume(tuppleOpt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.concurrent.TimeUnit;
import org.enso.compiler.Compiler;
import org.enso.compiler.benchmarks.Utils;
import org.enso.compiler.context.InlineContext;
import org.enso.polyglot.RuntimeOptions;
import org.graalvm.polyglot.Context;
import org.openjdk.jmh.annotations.Benchmark;
Expand Down Expand Up @@ -48,7 +47,7 @@ public class InlineCompilerErrorBenchmark {
private Compiler compiler;

private Context ctx;
private InlineContext mainInlineContext;
private InlineContextResourceBuilder mainInlineContextResourceBuilder;
private String expressionWithErrors;

@Setup
Expand All @@ -63,11 +62,12 @@ public void setup() throws IOException {
var ensoCtx = Utils.leakEnsoContext(ctx);
compiler = ensoCtx.getCompiler();

var inlineSource = InlineContextUtils.createMainMethodWithLocalVars(ctx, LOCAL_VARS_CNT);
var localVarNames = InlineContextUtils.localVarNames(LOCAL_VARS_CNT);
var inlineSource = InlineContextUtils.createMainMethodWithLocalVars(ctx, localVarNames);
var longExpression =
InlineContextUtils.createLongExpression(inlineSource.localVarNames(), LONG_EXPR_SIZE);
expressionWithErrors = "UNDEFINED * " + longExpression + " * UNDEFINED";
mainInlineContext = inlineSource.mainInlineContext();
mainInlineContextResourceBuilder = inlineSource.builder();
}

@TearDown
Expand All @@ -79,8 +79,10 @@ public void teardown() {
}

@Benchmark
public void expressionWithErrors(Blackhole blackhole) {
var tuppleOpt = compiler.runInline(expressionWithErrors, mainInlineContext);
blackhole.consume(tuppleOpt);
public void expressionWithErrors(Blackhole blackhole) throws IOException {
try (InlineContextResource resource = mainInlineContextResourceBuilder.build()) {
var tuppleOpt = compiler.runInline(expressionWithErrors, resource.inlineContext());
blackhole.consume(tuppleOpt);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.enso.compiler.benchmarks.inline;

import java.io.IOException;
import org.enso.compiler.context.InlineContext;
import scala.runtime.BoxedUnit;

/**
* InlineContextResource ensures that the underlying InlineContext is properly cleaned up after
* usage.
*
* @param inlineContext InlineContext for the main method
*/
public record InlineContextResource(InlineContext inlineContext) implements AutoCloseable {
@Override
public void close() throws IOException {
inlineContext
.localScope()
.foreach(
s -> {
s.scope().close();
return BoxedUnit.UNIT;
hubertp marked this conversation as resolved.
Show resolved Hide resolved
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.enso.compiler.benchmarks.inline;

import org.enso.compiler.PackageRepository;
import org.enso.compiler.context.InlineContext;
import org.enso.interpreter.node.MethodRootNode;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.data.Type;
import org.enso.interpreter.runtime.scope.ModuleScope;

public record InlineContextResourceBuilder(
hubertp marked this conversation as resolved.
Show resolved Hide resolved
ModuleScope moduleScope,
Type assocTypeReceiver,
EnsoContext ensoCtx,
PackageRepository pkgRepository) {

InlineContextResource build() {
var mainFunc = moduleScope.getMethodForType(assocTypeReceiver, "main");
var mainFuncRootNode = (MethodRootNode) mainFunc.getCallTarget().getRootNode();
var mainLocalScope = mainFuncRootNode.getLocalScope();
return new InlineContextResource(
InlineContext.fromJava(
mainLocalScope.createChild(),
moduleScope.getModule().asCompilerModule(),
scala.Option.apply(false),
ensoCtx.getCompilerConfig(),
scala.Option.apply(pkgRepository)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import java.util.Set;
import org.enso.compiler.benchmarks.CodeGenerator;
import org.enso.compiler.benchmarks.Utils;
import org.enso.compiler.context.InlineContext;
import org.enso.interpreter.node.MethodRootNode;
import org.enso.interpreter.runtime.data.Type;
import org.enso.polyglot.LanguageInfo;
import org.enso.polyglot.MethodNames;
Expand All @@ -16,25 +14,32 @@
class InlineContextUtils {
private InlineContextUtils() {}

static Set<String> localVarNames(int localVarsCnt) {
Set<String> localVarNames = new HashSet<>();

for (int i = 0; i < localVarsCnt; i++) {
var varName = "loc_var_" + i;
localVarNames.add(varName);
}
return localVarNames;
}

/**
* Creates a main method, generates some local variables, and fills their identifiers in the given
* set.
*
* @param localVarsCnt How many local variables should be initialized in the main method
* @return Body of the main method
*/
static InlineSource createMainMethodWithLocalVars(Context ctx, int localVarsCnt)
static InlineSource createMainMethodWithLocalVars(Context ctx, Set<String> localVarNames)
throws IOException {
var sb = new StringBuilder();
sb.append("main = ").append(System.lineSeparator());
var codeGen = new CodeGenerator();
Set<String> localVarNames = new HashSet<>();
for (int i = 0; i < localVarsCnt; i++) {
var varName = "loc_var_" + i;
localVarNames.add(varName);
for (String localVarName : localVarNames) {
var literal = codeGen.nextLiteral();
sb.append(" ")
.append(varName)
.append(localVarName)
.append(" = ")
.append(literal)
.append(System.lineSeparator());
Expand All @@ -51,18 +56,11 @@ static InlineSource createMainMethodWithLocalVars(Context ctx, int localVarsCnt)
var moduleAssocType = module.invokeMember(MethodNames.Module.GET_ASSOCIATED_TYPE);
var assocTypeReceiver = (Type) Utils.unwrapReceiver(ctx, moduleAssocType);
var moduleScope = assocTypeReceiver.getDefinitionScope();
var mainFunc = moduleScope.getMethodForType(assocTypeReceiver, "main");
var mainFuncRootNode = (MethodRootNode) mainFunc.getCallTarget().getRootNode();
var mainLocalScope = mainFuncRootNode.getLocalScope();
var compiler = ensoCtx.getCompiler();
var mainInlineContext =
InlineContext.fromJava(
mainLocalScope,
moduleScope.getModule().asCompilerModule(),
scala.Option.apply(false),
ensoCtx.getCompilerConfig(),
scala.Option.apply(compiler.packageRepository()));
return new InlineSource(sb.toString(), mainInlineContext, localVarNames);
var inlineCtxMeta =
new InlineContextResourceBuilder(
moduleScope, assocTypeReceiver, ensoCtx, compiler.packageRepository());
return new InlineSource(sb.toString(), inlineCtxMeta, localVarNames);
}

static String createLongExpression(Set<String> localVars, int exprSize) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package org.enso.compiler.benchmarks.inline;

import java.util.Set;
import org.enso.compiler.context.InlineContext;

record InlineSource(
String source,
// InlineContext for the main method
InlineContext mainInlineContext,
// Builder for InlineContext for the main method
InlineContextResourceBuilder builder,
// Local variables in main method
Set<String> localVarNames) {}
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,17 @@ object Graph {

isDirectChildOf || isChildOfChildren
}

private def removeScope(scope: Scope): Unit = {
childScopes = childScopes.filter(_ != scope)
hubertp marked this conversation as resolved.
Show resolved Hide resolved
}

/** Disassociates this Scope from its parent.
*/
def close(): Unit = {
assert(this.parent.nonEmpty)
this.parent.foreach(_.removeScope(this))
}
}

/** A link in the [[Graph]].
Expand Down
Loading