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

Add ExportImportResolutionBenchmark #10043

Merged
merged 29 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
5bbd576
Move TestBase into a new project test-utils
Akirathan May 22, 2024
9e70f67
Add ExportImportResolutionBenchmark.
Akirathan May 22, 2024
99cad2e
Add unit test for exports symbol restrictions and module order
Akirathan May 27, 2024
4512650
Do not optimize symbols in ExportsResolution
Akirathan May 29, 2024
5c902bf
Revert "Add ExportImportResolutionBenchmark."
Akirathan May 30, 2024
0df3ceb
Revert "Move TestBase into a new project test-utils"
Akirathan May 30, 2024
06818be
Merge branch 'refs/heads/develop' into wip/akirathan/9236-improve-imp…
Akirathan May 30, 2024
b626421
Add ExportImportResolutionBenchmark
Akirathan May 30, 2024
b62d0d3
Revert "Do not optimize symbols in ExportsResolution"
Akirathan May 30, 2024
cc83ef0
Remove ExportResolutionTest
Akirathan May 30, 2024
f0a99fd
Add ExportedSymbolsTest
Akirathan May 30, 2024
820cfe8
Add ExportCycleDetectionTest
Akirathan May 30, 2024
0b8932d
ProjectUtils: Main module does not have to exist when creating a project
Akirathan Jun 4, 2024
6064dc4
Add test-utils to sbt aggregate
Akirathan Jun 4, 2024
5ca3735
fmt
Akirathan Jun 4, 2024
adc3815
Add test for symbol hiding
Akirathan Jun 4, 2024
b7fbb85
Remove ExportCycleDetectionTest
Akirathan Jun 6, 2024
e84a2f9
Merge branch 'refs/heads/develop' into wip/akirathan/9236-improve-imp…
Akirathan Jun 6, 2024
157df9c
Do not optimize symbols in ExportsResolution
Akirathan Jun 6, 2024
a66b6eb
Merge branch 'refs/heads/develop' into wip/akirathan/9236-improve-imp…
Akirathan Jun 11, 2024
6c2c1b5
Revert "Do not optimize symbols in ExportsResolution"
Akirathan Jun 11, 2024
a048114
Reintroduce ExportCycleDetectionTest
Akirathan Jun 11, 2024
35113c2
Add test for exported symbols in synthetic modules
Akirathan Jun 11, 2024
ab6d733
Add test for export cycle detection in three modules
Akirathan Jun 11, 2024
712d99b
Remove unnecessary imports from tests
Akirathan Jun 11, 2024
ed225d3
Minoc docs fix - remove non-existing link
Akirathan Jul 12, 2024
cb05246
Merge branch 'refs/heads/develop' into wip/akirathan/9236-improve-imp…
Akirathan Jul 12, 2024
aa722df
Fix of imports after merge with develop
Akirathan Jul 12, 2024
971ea6e
fmt
Akirathan Jul 12, 2024
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
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2195,6 +2195,7 @@ lazy val `runtime-benchmarks` =
)
.dependsOn(`runtime-fat-jar`)
.dependsOn(`benchmarks-common`)
.dependsOn(`test-utils`)

lazy val `runtime-parser` =
(project in file("engine/runtime-parser"))
Expand Down
1 change: 0 additions & 1 deletion docs/infrastructure/sbt.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ compilation. The build configuration is defined in
<!-- MarkdownTOC levels="2,3" autolink="true" -->

- [Incremental Compilation](#incremental-compilation)
- [Bootstrapping](#bootstrapping)
- [Compile Hooks](#compile-hooks)
- [Helper Tasks](#helper-tasks)
- [Graal and Flatc Version Check](#graal-and-flatc-version-check)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package org.enso.compiler.benchmarks.exportimport;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.enso.common.CompilationStage;
import org.enso.compiler.benchmarks.Utils;
import org.enso.compiler.context.CompilerContext;
import org.enso.compiler.phase.ImportResolver;
import org.enso.compiler.phase.exports.ExportCycleException;
import org.enso.compiler.phase.exports.ExportsResolution;
import org.enso.interpreter.runtime.Module;
import org.enso.pkg.QualifiedName;
import org.enso.polyglot.RuntimeOptions;
import org.enso.test.utils.ContextUtils;
import org.enso.test.utils.ProjectUtils;
import org.enso.test.utils.SourceModule;
import org.graalvm.polyglot.Context;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.BenchmarkParams;
import org.openjdk.jmh.infra.Blackhole;
import scala.jdk.javaapi.CollectionConverters;

/**
* Benchmarks that measure performance of only {@link ImportResolver} and {@link ExportsResolution}.
*/
@BenchmarkMode(Mode.AverageTime)
@Fork(1)
@Warmup(iterations = 6)
@Measurement(iterations = 4)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
public class ExportImportResolutionBenchmark {
private Path projDir;
private OutputStream out;
private Context ctx;
private ImportResolver importResolver;
private ExportsResolution exportsResolution;
private CompilerContext.Module mainModule;
private scala.collection.immutable.List<CompilerContext.Module> modulesToExportResolution;
private scala.collection.immutable.List<CompilerContext.Module> resolvedModules;

@Setup
public void setup(BenchmarkParams params) throws IOException {
this.out = new ByteArrayOutputStream();
var mainMod =
new SourceModule(
QualifiedName.fromString("Main"),
"""
from Standard.Base import all
""");
this.projDir = Files.createTempDirectory("export-import-resolution-benchmark");
ProjectUtils.createProject("Proj", Set.of(mainMod), projDir);
// Create temp proj dir
this.ctx =
Utils.createDefaultContextBuilder()
.option(RuntimeOptions.PROJECT_ROOT, projDir.toAbsolutePath().toString())
.out(out)
.err(out)
.build();
var ensoCtx = ContextUtils.leakContext(ctx);
this.mainModule = ensoCtx.getPackageRepository().getLoadedModule("local.Proj.Main").get();
var mainRuntimeMod = Module.fromCompilerModule(mainModule);
assertThat(
"main module should not yet be compiled",
mainRuntimeMod.getCompilationStage().equals(CompilationStage.INITIAL));
this.importResolver = new ImportResolver(ensoCtx.getCompiler());
this.exportsResolution = new ExportsResolution(ensoCtx.getCompiler().context());
}

@TearDown
public void teardown(BenchmarkParams params) throws IOException {
if (!out.toString().isEmpty()) {
throw new AssertionError("Unexpected output (errors?) from the compiler: " + out.toString());
}
ProjectUtils.deleteRecursively(projDir);
ctx.close();

// It is expected that there are more than 20 modules in Standard.Base, and all of them
// should have been processed. Note that 20 is just a magic constant for sanity check.
assertThat(modulesToExportResolution.size() > 20);
var mods = CollectionConverters.asJava(modulesToExportResolution);
for (var mod : mods) {
var isImportResolved =
mod.getCompilationStage().isAtLeast(CompilationStage.AFTER_IMPORT_RESOLUTION);
assertThat(
"Module '" + mod.getName() + "' is not resolved after import resolution",
isImportResolved);
}

var benchName = params.getBenchmark();
if (benchName.contains("runImportExportResolution")) {
assertThat(resolvedModules.size() > 20);
for (var mod : CollectionConverters.asJava(resolvedModules)) {
var isExportResolved =
mod.getCompilationStage().isAtLeast(CompilationStage.AFTER_IMPORT_RESOLUTION);
assertThat(
"Module '" + mod.getName() + "' is not resolved after export resolution",
isExportResolved);
}
}
}

@Benchmark
public void importsResolution(Blackhole blackhole) {
var res = importResolver.mapImports(mainModule, false);
modulesToExportResolution = res._1;
blackhole.consume(res);
}

/**
* {@link ExportsResolution export resolver} needs to be run after the imports resolution, so in
* this benchmark, we run both import resolution and export resolution. In the other benchmark,
* only import resolution is run.
*/
@Benchmark
public void importsAndExportsResolution(Blackhole blackhole) throws ExportCycleException {
var res = importResolver.mapImports(mainModule, false);
modulesToExportResolution = res._1;
resolvedModules = exportsResolution.run(modulesToExportResolution);
blackhole.consume(resolvedModules);
}

/**
* These utility methods are used because simple {@code assert} statement might not work -
* benchmarks are usually run without assertions enabled. This just makes sure that the given
* condition is checked and not ignored.
*/
private static void assertThat(boolean condition) {
assertThat("", condition);
}

private static void assertThat(String msg, boolean condition) {
if (!condition) {
throw new AssertionError(msg);
}
}
}
Loading