Question

I have a fairly basic wrapper class around a scala akka actorRef. Basically the class has a field which is an actorRef and exposes a number of methods that "tell" specific messages to the actorRef. In this fashion I can adhere to a specify API and avoid exposing tells or message classes. I've experienced a memory leak in my program and I'm wondering if my wrapper around akka actors is causing the problem. I wrote this simulation below to test my theory.

import akka.actor.{ActorSystem, ActorRef, PoisonPill}
import akka.actor.ActorDSL._

implicit val as = ActorSystem()

def createMemoryActor(): ActorRef = actor(new Act {
  Array.fill(99999999)(1.0) // Just to take up memory
  become {
    case _ => print("testing memory leaks")
  }
})

val memoryActor = createMemoryActor() // memory usage jumps up

memoryActor ! PoisonPill
System.gc() // memory usage goes back down

case class ActorWrapper() {
  val memoryActor = createMemoryActor()
}

def doNothing(): Unit = {
  val shouldGetGCed = ActorWrapper()
  ()
}

doNothing() // memory usage jumps up
System.gc() // memory usage goes back down

I've run the above code in a scala repl and run jvisualvm to profile the memory usage. It seems that the "shouldGetGCed" reference gets garage collected and its actorRef field (which was taking up memory) also gets garbage collected. Is this always the case or am I missing something? Also anyone have any best practices for wrapping actors to adhere to specific APIs?

Was it helpful?

Solution

Every actor that is started must eventually be stopped, and until that happens it will consume memory. In your example you need to e.g. shouldGetGCed.memoryActor ! PoisonPill. There is no automatic garbage collection for actors since they are distributed entities by nature and the JVM does not support distributed GC.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top