Basic profiling using sbt

I would like to do some basic profiling as simply as possible (without installing anything, if possible). I was using the Java Xprof option, as in

export JAVA_OPTS="-Xmx8192M -Xms8192M -Xprof"

That works when I invoke my program from the command line, but it does not give me any profiling data on my own program when I invoke it with sbt. Is there a simple way to get this profiling, or something similar, when running a program with sbt?

Also, incidentally, what is a good way to set the Java memory limits using JAVA_OPTS? Thanks.

Is it possible you’re being bit by the sbt forking configuration? sbt Reference Manual — Forking

If your code is running in a different process than the sbt one perhaps that would result in the profiling behavior you are seeing where the output only covers sbt itself. I think in those cases you might want to use the extra Java opts configuration for the forked run to pass the options you need through:
https://www.scala-sbt.org/1.x/docs/Forking.html#Forked+JVM+options

FWIW I’ve had great success with the Java Async Profiler lately: GitHub - jvm-profiling-tools/async-profiler: Sampling CPU and HEAP profiler for Java featuring AsyncGetCallTrace + perf_events. I found it quite easy to setup and generate flamegraphs.

Thanks for the reply. Yes, I am forking in sbt. I added

run / javaOptions += “-Xprof”

in my build.sbt file, and now I am getting profiling data on my own code. Unfortunately, it is still not very helpful. I don’t know how to interpret the results, and online searches don’t seem to help much. My program got a lot slower after some refactoring and bug fixes, and I am trying to figure out why.

I see a lot of stuff like this:

 Compiled + native   Method                        

30.5% 936 + 0 ExceptionBlob

What is this telling me?

I may try another profiling tool, but I’m not quite at that point yet.

Great, glad you got it working

Unfortunately, it is still not very helpful. I don’t know how to interpret the results

Yeah, that’s always the rub with these things. I’m afraid I can’t offer much help on interpreting prof results but I definitely share your pain that these things can often be pretty inscrutable. Flamegraphs are the only ones I’ve found to be slightly intuitive without a ton of prior study. It used to be kind of a pain to generate them for the JVM, but that async profiler has made it a lot easier

Here is what I have done a fair amount (there may be better options, but this is the best of those I tried).
(1) Use the Java async profiler, as mentioned above, to record a jfr file.
(2) Open this in Java Mission Control (jmc from the command line).
(3) Trace the code and find where most time was being taken.
In many cases this showed what needed to be optimized (e.g. by memoizing).

regards,
Siddhartha

1 Like