In the process of learning Scala, or trying to understand a particular problem, you want to examine the source code and bytecode the Scala compiler generates from your original source code.Back to top
You can use several different approaches to see how your Scala source code is translated:
If you’re ever working on a really small Scala project — something that contains only a few source code files — and don’t want to use SBT to create a JAR file, you can do it yourself manually. Let’s look at a quick example. Note that the commands below work on Mac and Linux systems, and should work on Windows with minor changes.
What def, val, and var fields in Scala traits look like after they’re compiled (including the classes that extend them)
I generally have a pretty good feel for how Scala traits work, and how they can be used for different needs. As one example, a few years ago I learned that it’s best to define abstract fields in traits using
def. But there are still a few things I wonder about.
Today I had a few free moments and I decided to look at what happens under the covers when you use
var fields in traits, and then mix-in or extend those traits with classes. So I created some examples, compiled them with
scalac -Xprint:all, and then decompiled them with JAD to see what everything looks like under the covers.
I was initially going to write a summary here, but if you want to know how things work under the hood, I think it helps to work through the examples, so for today I’ll leave that as an exercise for the reader.
I had read that Bloop was faster than Scala compiler tools like
fsc, so I wondered if it was faster than SBT, and if so, how much faster. So I downloaded Eric Torreborre’s specs2 source code, which has 880 source code files, and compiled the entire project with both SBT and Bloop.
To test SBT’s speed, I ran all the commands from inside the SBT command prompt, which I usually do anyway to avoid the SBT/JVM startup lag time. I also ran
compile several times before recording SBT’s speed, because I thought that would be a better reflection of real-world usage and performance. I ran the tests four times, and the average time with SBT was 49 seconds, and that was very consistent, always coming in between 48 and 50 seconds.
As a quick note to self, here’s an example of how to set
scalacOptions in an SBT build.sbt file:
scalacOptions ++= Seq( "-Xfatal-warnings", "-deprecation", "-feature", "-unchecked", "-language:implicitConversions", "-language:higherKinds", "-language:existentials", "-language:postfixOps" )
scalacOptions lets you set Scala compiler options in your SBT project build.
scala-lang.org has an article titled Speeding Up Compilation Time with `scalac-profiling` where they demonstrate how they reduced a project’s compilation time from 32.5 seconds down to 4 seconds. In addition to all of the scalac and profiling details, it demonstrates a nice use of flamegraphs.
This typesafe.com chart shows the results of the efforts to make the Scala compiler faster over the last several years.
I haven’t tried it yet, but as a note to self, Scala 2.12.5 introduced a new
-Ybackend-parallelism N compiler flag with which “the backend can now run in parallel on N threads.”
If you ever need definitions of
scalac compiler options (up to Scala 2.12.2), here you go.
This is a page from my book, Functional Programming, Simplified
When I update the Scala Cookbook, I need to update Recipe 8.2, “How to use abstract and concrete fields in Scala traits.” That recipe is written particularly with an OOP developer in mind, and I didn’t write about handling the same situation from an FP perspective.