enso/docs/debugger/runtime-debugging.md
Pavel Marek 8e49255d92
Invoke all Enso benchmarks via JMH (#7101)
# Important Notes
#### The Plot

- there used to be two kinds of benchmarks: in Java and in Enso
- those in Java got quite a good treatment
- there even are results updated daily: https://enso-org.github.io/engine-benchmark-results/
- the benchmarks written in Enso used to be 2nd class citizen

#### The Revelation
This PR has the potential to fix it all!
- It designs new [Bench API](88fd6fb988) ready for non-batch execution
- It allows for _single benchmark in a dedicated JVM_ execution
- It provides a simple way to wrap such an Enso benchmark as a Java benchmark
- thus the results of Enso and Java benchmarks are [now unified](https://github.com/enso-org/enso/pull/7101#discussion_r1257504440)

Long live _single benchmarking infrastructure for Java and Enso_!
2023-08-07 12:39:01 +00:00

3.1 KiB

Runtime (Engine) debugging

This section explains how to debug various parts of the Engine. By Engine, we mean all the Java code located in the runtime SBT project, in engine directory.

Debugging source file evaluation

This subsection provides a guide how to debug a single Enso source file evaluation. To evaluate a single source file, we use the Engine distribution built with buildEngineDistribution command. Both of the following two options starts the JVM in a debug mode. After the JVM is started in a debug mode, simply attach the debugger to the JVM process at the specified port.

The first option is to invoke the engine distribution from SBT shell with:

sbt:enso> runEngineDistribution --debug --run ./test/Tests/src/Data/Numbers_Spec.enso

The second options is to pass in special JVM arguments when launching the bin/enso from the engine distribution:

enso$ JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=n,address=5005 ./built-distribution/enso-engine-*/enso-*/bin/enso --run ./test/Tests/src/Data/Numbers_Spec.enso

Tips and tricks

There is no simple mapping of the Enso source code to the engine's Java code, so if you try to debug a specific expression, it might be a bit tricky. However, the following steps should help you to skip all the irrelevant code and get to the code you are interested in:

  • To debug a method called foo, put a breakpoint in org.enso.interpreter.node.ClosureRootNode#execute with a condition on this.name.contains("foo")
  • To debug a specific expression, put some unique expression, like Debug.eval "1+1", in front of it and put a breakpoint in a Truffle node corresponding to that unique expression, in this case that is org.enso.interpreter.node.expression.builtin.debug.DebugEvalNode.

Debugging annotation processors

The Engine uses annotation processors to generate some of the Java code, e.g., the builtin methods with org.enso.interpreter.dsl.MethodProcessor, or JMH benchmark sources with org.enso.benchmarks.processor.BenchProcessor. Annotation processors are invoked by the Java compiler (javac), therefore, we need special instructions to attach the debugger to them.

Let's debug org.enso.interpreter.dsl.MethodProcessor as an example. The following are the commands invoked in the sbt shell:

  • project runtime
  • clean
    • Delete all the compiled class files along with all the generated sources by the annotation processor. This ensures that the annotation processor will be invoked.
  • set javacOptions += FrgaalJavaCompiler.debugArg
    • This sets a special flag that is passed to the frgaal Java compiler, which in turn waits for the debugger to attach. Note that this setting is not persisted and will be reset once the project is reloaded.
  • compile
    • Launches the Java compiler, which will wait for the debugger to attach. Put a breakpoint in some class of org.enso.interpreter.dsl package. Wait for the message in the console instructing to attach the debugger.
  • To reset the javacOptions setting, either run set javacOptions -= FrgaalJavaCompiler.debugArg, or reload the project with reload.