Performance & the JVM
GC choice (G1 default, ZGC/Shenandoah for low latency), heap sizing (-Xms, -Xmx), -XX:+UseZGC, JIT warm-up, GraalVM native-image for fast startup.
38.1 Tips
Choose the right collection (Vector/ArraySeq for indexed access, Array for hot numeric loops).
Avoid repeated :+ on List; build with :: + reverse or use builders (List.newBuilder).
Use view/iterator to avoid intermediate collections in long pipelines.
Beware boxing in generic code; use Array[Int], specialized libraries (Spire), or inline.
Use while loops in performance-critical inner loops.
Prefer StringBuilder/mkString over repeated concatenation.
Use lazy val judiciously (it has synchronization cost).
Opaque types instead of wrapper classes.
Profile before optimizing.
38.2 Benchmarking & profiling
JMH via sbt-jmh:
Profilers: async-profiler, VisualVM, JDK Flight Recorder / Mission Control, YourKit.
import org.openjdk.jmh.annotations.*
@State(Scope.Thread)
class Bench:
val xs = (1 to 10000).toList
@Benchmark def sumList: Int = xs.sum
@Benchmark def sumWhile: Int = { var i = 0; var s = 0; val a = xs.toArray; while i < a.length do { s += a(i); i += 1 }; s }sbt "Jmh/run -i 5 -wi 3 -f1"38.3 JVM tuning
GC choice (G1 default, ZGC/Shenandoah for low latency), heap sizing (-Xms, -Xmx), -XX:+UseZGC, JIT warm-up, GraalVM native-image for fast startup.
38.4 Compile times
Keep implicits/givens scoped, avoid huge derivations, modularize builds, use incremental compilation (Zinc), Bloop, and remote caching.