diff --git a/ownlang-parser/build.gradle b/ownlang-parser/build.gradle index 5e06268..0354e96 100644 --- a/ownlang-parser/build.gradle +++ b/ownlang-parser/build.gradle @@ -14,6 +14,7 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation "org.openjdk.jmh:jmh-core:${versions.jmh}" testImplementation "org.openjdk.jmh:jmh-generator-annprocess:${versions.jmh}" + testAnnotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${versions.jmh}" } test { diff --git a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/LexerBenchmarkTest.java b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/LexerBenchmarkTest.java index b654fff..8fa8421 100644 --- a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/LexerBenchmarkTest.java +++ b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/LexerBenchmarkTest.java @@ -6,6 +6,7 @@ import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.Options; @@ -23,13 +24,13 @@ public class LexerBenchmarkTest { @Setup(Level.Trial) public void initializeTrial() throws IOException { - input = SourceLoader.readSource("program.own"); + input = SourceLoader.readSource("../program.own"); } @Benchmark - public void lexerBenchmark() { + public void lexerBenchmark(Blackhole bh) { for (int i = 0; i < iterations; i++) { - Lexer.tokenize(input); + bh.consume(Lexer.tokenize(input)); } } diff --git a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ParserBenchmarkTest.java b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ParserBenchmarkTest.java index 68e3b93..05c867e 100644 --- a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ParserBenchmarkTest.java +++ b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ParserBenchmarkTest.java @@ -25,7 +25,7 @@ public class ParserBenchmarkTest { @Setup(Level.Trial) public void initializeTrial() throws IOException { - input = Lexer.tokenize(SourceLoader.readSource("program.own")); + input = Lexer.tokenize(SourceLoader.readSource("../program.own")); } @Benchmark diff --git a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsBenchmarkTest.java b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsBenchmarkTest.java new file mode 100644 index 0000000..cf89831 --- /dev/null +++ b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsBenchmarkTest.java @@ -0,0 +1,64 @@ +package com.annimon.ownlang.parser; + +import com.annimon.ownlang.parser.ast.Statement; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; + +import static com.annimon.ownlang.parser.TestDataUtil.scanDirectory; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class ProgramsBenchmarkTest { + private static final String RES_DIR = "src/test/resources/benchmarks"; + + @Param({"10"}) + private int iterations; + @Param({"-"}) + private String path; + + private Statement program; + + @Setup(Level.Trial) + public void initializeTrial() throws IOException { + if (!Files.exists(Path.of(path))) return; + final var source = SourceLoader.readSource(path); + final var tokens = Lexer.tokenize(source); + program = Parser.parse(tokens); + } + + @Benchmark + public void programBenchmark() { + for (int i = 0; i < iterations; i++) { + program.execute(); + } + } + + @Disabled + @Test + public void executeBenchmark() throws RunnerException { + Options opt = new OptionsBuilder() + .include(ProgramsBenchmarkTest.class.getSimpleName()) + .warmupIterations(3) + .measurementIterations(5) + .param("path", scanDirectory(RES_DIR) + .map(File::getPath) + .toArray(String[]::new)) + .threads(1) + .forks(1) + .build(); + + new Runner(opt).run(); + } +} diff --git a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java index caa2708..e9bb36f 100644 --- a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java +++ b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java @@ -18,35 +18,19 @@ import org.junit.jupiter.params.provider.MethodSource; import java.io.File; import java.io.IOException; -import java.util.Arrays; import java.util.stream.Stream; +import static com.annimon.ownlang.parser.TestDataUtil.scanDirectory; import static org.junit.jupiter.api.Assertions.*; public class ProgramsTest { private static final String RES_DIR = "src/test/resources"; public static Stream data() { - final File resDir = new File(RES_DIR); - return scanDirectory(resDir) + return scanDirectory(RES_DIR) .map(File::getPath); } - private static Stream scanDirectory(File dir) { - final File[] files = dir.listFiles(); - if (files == null || files.length == 0) { - return Stream.empty(); - } - return Arrays.stream(files) - .flatMap(file -> { - if (file.isDirectory()) { - return scanDirectory(file); - } - return Stream.of(file); - }) - .filter(f -> f.getName().endsWith(".own")); - } - @BeforeEach public void initialize() { Variables.clear(); diff --git a/ownlang-parser/src/test/java/com/annimon/ownlang/parser/TestDataUtil.java b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/TestDataUtil.java new file mode 100644 index 0000000..fa239bf --- /dev/null +++ b/ownlang-parser/src/test/java/com/annimon/ownlang/parser/TestDataUtil.java @@ -0,0 +1,22 @@ +package com.annimon.ownlang.parser; + +import java.io.File; +import java.util.Arrays; +import java.util.stream.Stream; + +public class TestDataUtil { + + static Stream scanDirectory(String dirPath) { + return scanDirectory(new File(dirPath)); + } + + static Stream scanDirectory(File dir) { + final File[] files = dir.listFiles(); + if (files == null || files.length == 0) { + return Stream.empty(); + } + return Arrays.stream(files) + .flatMap(f -> f.isDirectory() ? scanDirectory(f) : Stream.of(f)) + .filter(f -> f.getName().endsWith(".own")); + } +} diff --git a/ownlang-parser/src/test/resources/benchmarks/useStatement.own b/ownlang-parser/src/test/resources/benchmarks/useStatement.own new file mode 100644 index 0000000..0e72fec --- /dev/null +++ b/ownlang-parser/src/test/resources/benchmarks/useStatement.own @@ -0,0 +1,5 @@ +for i = 0, i < 50, i++ { + use "std" + use "files" + use ["math", "functional"] +} \ No newline at end of file