Scala3 compiler out if heap memory

Hi Community,

In a not so small project (>200 files, >22K lines of code) a get an “java.lang.OutOfMemoryError: Java heap space” error on the compilation with SBT 1.6.2 and Scala 3.1.1. This happens after the compiler has run for 965 seconds. The max heap size was set to 24GB. The code is warning and error free. The same code compiles under scala 2.13.6 in 40 seconds within 1.5GB of heap. Where do i start to analyse this problem? Btw: I have ported other projects from Scala2 to Scala3 without any issues.

Thanks for any tips.
Ruud.

1 Like

Just to comment on myself, i think i found the offending part. It is somehow related to the “too large method” issue. But the method seems even larger than “too large” :grinning: Anyhow, i will try to synthesise a small example.

This is the minimal example (derived from a real world application):

/**  Compile with:
sbt.version=1.6.2
scalaVersion := "3.1.1"
scalacOptions ++= Seq("-feature","-deprecation","-unchecked","-explain"),
libraryDependencies ++= Seq("com.softwaremill.quicklens" %% "quicklens" % "1.8.3")                                   
*/

package HeapError

import com.softwaremill.quicklens._

/* Presence of AnyVal turns 'MethodTooLargeException' into an 
   'java.lang.OutOfMemoryError: Java heap space' error */
class Moment(val value: Long) extends AnyVal with Ordered[Moment]
{ def compare(that: Moment) = (this.value - that.value).sign.toInt
  def isZero = value == 0 }
  
case class Timers(
  wakeTime:            Moment, 
  constructionTime:    Moment, 
  initializationTime:  Moment, 
  activationTime:      Moment, 
  clock:               Moment, 
  lastSignal:          Moment, 
  lastTransmission:    Moment, 
  lastHeartbeat:       Moment, 
  lastClockSet:        Moment, 
  lastFail:            Moment) 

case class Counters(
  missedAcks:   Int, 
  upSinceHB:    Int, 
  downSinceHB:  Int, 
  failSinceHB:  Int, 
  upSum:        Int, 
  downSum:      Int, 
  failSum:      Int) 

case class SystemState(
  mcuTemperature: Double, 
  batteryCharge:  Double, 
  bufferSpace:    Double, 
  health:         Double)
 
case class Monitor(timers: Timers, counters: Counters, systemState: SystemState) 
{ def setClockInit(time: Moment): Monitor = this
    .modifyAll(_.timers.clock, 
               _.timers.initializationTime,  
               _.timers.lastClockSet, 
               _.timers.lastSignal, 
               _.timers.lastTransmission)
    .setToIf(!time.isZero)(time) }

It looks likes this counts as a compiler bug. Opinions? Should this be posted on the issue bord of the dotty compiler?

Might be worth asking on Contributors, but my instinct is to say yes – an OOM during compilation (with plenty of memory present, which it sounds like you have) is probably a compiler bug by definition…

1 Like

Thank you. I decided to post this as a reply to the open issue “Do not crash in backend when method is too large”, since it is most likely closely related to that.

1 Like