-
Notifications
You must be signed in to change notification settings - Fork 321
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
Invoke all Enso benchmarks via JMH #7101
Conversation
...untime/src/bench/resources/org.enso.interpreter.bench.benchmarks.meso/Vector_Operations.enso
Outdated
Show resolved
Hide resolved
@Akirathan could we also combine this with #6554? |
Well, this kind of supersedes #6554 - if this is integrated, there will be no more need for Enso benchmarks |
39fc4c9
to
188d465
Compare
engine/runtime/src/bench/scala/org/enso/interpreter/bench/IRUtils.scala
Outdated
Show resolved
Hide resolved
Current idea of the solution (sketched in f6dd423):
Another alternative is to generate many Java sources with many methods annotated with IR manipulation is out of the question - better to refactor This idea assumes that all the benchmarks in |
engine/runtime/src/bench/java/org/enso/interpreter/bench/benchmarks/meso/LibBenchRunner.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just used this support to execute Greg's benchmarks and see the results in IGV. I think the support is good enough.
- Use `env JAVA_OPTS=-Dpolyglot.inspect.Path=enso_debug` to set the chrome to | ||
use a fixed URL. In this case the URL is | ||
`devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/enso_debug` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow I did not know that, so cool!
|
||
The `std-benchmarks` SBT project supports `bench` and `benchOnly` commands, that | ||
work the same as in the `runtime` project, with the exception that the benchmark | ||
name does not have to be specified as a fully qualified name, but as a regular |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this not work in runtime
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(using regexp to filter benchmarks)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet, I will look into that in one of the follow-up PRs and unify the functionality even more.
lib/scala/bench-processor/src/main/java/org/enso/benchmarks/BenchConfig.java
Show resolved
Hide resolved
*/ | ||
public interface BenchSpec { | ||
String name(); | ||
Value code(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it really the code
or more like an executable thunk?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's exactly the same as code
field in Bench.Spec
, as mentioned in the javadoc. It's just a polyglot org.graalvm.polyglot.Value
that can be executed. I guess that technically it is a thunk, but what difference does it make here?
if (debugAnotProcessorOpt) { | ||
log.info( | ||
s"Frgaal compiler is about to be launched with $debugArg, which means that" + | ||
" it will wait for a debugger to attach. The output from the compiler is by default" + | ||
" redirected, therefore \"Listening to the debugger\" message will not be displayed." + | ||
" You should attach the debugger now." | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, thanks for adding this message!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without that message, you would have no idea that the java
process is waiting for a debugger, because the output is redirected.
random_vec = Utils.make_random_vec 100000 | ||
uniform_vec = Vector.fill 100000 1 | ||
random_text_vec = random_vec.map .to_text | ||
uniform_text_vec = random_vec.map .to_text |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not good.
Enso has a subtle difference between top-level and scoped definitions, that plays a very crucial role here.
A scoped definition is computed (unless it's a block...) and stored. A top-level definition is re-computed on every access.
Essentially you have turned values computed once at initialization of the suite into 0-argument methods that are recomputed on each access.
This changes the semantics of these benchmarks.
We used to be just computing the time needed to compute the distinct
operation. Now we are computing the total time it takes to both generate the vector and compute distinct.
I don't think that's right.
I know that we don't have the 'setup' pattern yet. For now I'd just run this inside of the group
. It's not perfect and will slow down gathering benchmarks, so maybe for future we need a better solution.
On the other hand, I'm not 100% convinced that changing semantics is bad here. I don't think it is good but feel free to convince me otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A scoped definition is computed (unless it's a block...) and stored. A top-level definition is re-computed on every access.
I have not realized that. That might be problematic here - we don't want a different random_vec
in each iteration. I will try to revert that. My goal here was just to demonstrate the usage of the builder pattern that is syntactically a bit nicer than the usage in Operations.enso
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, let me take care of this in follow-up PRs, I have now added it to a task list in #7489.
@@ -39,7 +41,8 @@ public BenchmarkItem run(String label) throws RunnerException, JAXBException { | |||
if (Boolean.getBoolean("bench.compileOnly")) { | |||
builder | |||
.measurementIterations(1) | |||
.warmupIterations(0); | |||
.warmupIterations(0) | |||
.forks(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting forks to 0 when bench.CompileOnly = true
seems to have a negative side effect when all the benchmarks are run on the CI - it seems to cause StackOverflow errors, like this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reverts commit 95e6dea.
@@ -29,6 +29,9 @@ object FrgaalJavaCompiler { | |||
val frgaal = "org.frgaal" % "compiler" % "19.0.1" % "provided" | |||
val sourceLevel = "19" | |||
|
|||
val debugArg = | |||
"-J-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=localhost:8000" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this option shall be unified with WithDebugCommand
setup... I wanted to mention that before, but maybe I haven't done so...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have mentioned that already. And the answer is buried somewhere within dozens of comments in this PR. The brief answer is that we need the javac
process (more specifically, in this case, java -jar frgaal-compiler.jar
process) to wait for the debugger and not to start without it. That is because the java -jar frgaal-compiler.jar
process's output is piped, so the compiler process can finish even before the user notices that they could attach a debugger.
Moreover, using WithDebugCommand.DEBUG_ARG
requires some more refactoring - for that, we would need to remove some files in project
directory from org.enso.build
package.
TL;DR; it would be unnecessarily complicated.
Closes #7323
Pull Request Description
Motivation
There are a lot of Enso-only benchmarks in
test/Benchmarks
project. These benchmarks are not run on the CI (they are, but only in dry-run). We want to run these benchmarks and collect the results, such that we will see them in engine-benchmark-results along with all the other Engine bench results. These benchmarks use our Enso benchmarking infrastrcture, which basically consist of just one method -Bench.measure
.In order to do that, we have two choices:
Let's invoke every benchmark via JMH. Not only it collects the results for us, but it also does a lot of additional work like JVM preparation, forking, warmup, etc. We don't want to lose that ability.
Ideal properties of the solution:
How to use it
This PR adds two new SBT projects -
bench-processor
inlibs/scala/bench-processor
directory, andstd-benchmarks
instd-bits/benchmarks
directory.std-benchmarks
has just one Java class with themain
method and with@GenerateBenchSources
annotation.To run one benchmark:
To force the annotation processor to rediscover new benchmarks and to regenerate the JMH sources:
To provide additional cmdline arguments that are supported by JMH runner:
More info in
docs/infrastructure/benchmarks.md
Important Notes
The Plot
The Revelation
This PR has the potential to fix it all!
Long live single benchmarking infrastructure for Java and Enso!
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
./run ide build
.