Memory leak in Akka when using a scala stream - scala

Say I have the following:
def iterator[T](name: String, stream: Stream[T])(handlers: Seq[Behavior[Option[T]]]) = {
ActorSystem(Behaviors.setup[Option[T]] { context =>
val actors = handlers.map(context.spawnAnonymous(_))
context.spawnAnonymous(iterate(actors, stream))
actors.foreach(_ ! None)
Behavior.stopped
}, name)
}
def iterate[T](actors: Seq[ActorRef[Option[T]]], s: Stream[T]): Behavior[Any] = s match {
case h #:: t =>
actors.foreach(_ ! Some(h))
iterate(actors, t)
case _ =>
Behaviors.stopped
}
This will cause a memory leak with my stream members never getting freed. If I move the iterate call to outside of an actor behavior it works fine. I inspected my program with VisualVM and found the following is maintaining a reference to the head of the stream:
factory$1inakka.actor.typed.internal.BehaviorImpl$DeferredBehavior$$anon$1#1
Is there a way I can do my iteration in a separate Behavior while ensuring my stream references are freed up?

Related

Am I safely mutating in my akka actors or is this not thread safe?

I am a little confused if I am safely mutating my mutable maps/queue inside of my actor.
Can someone tell me if this code is thread-safe and correct?
class SomeActor extends Actor {
val userQ = mutable.Queue.empty[User]
val tranQ = mutable.Map.empty[Int, Transaction]
def receive = {
case Blank1 =>
if(userQ.isEmpty)
userQ ++= getNewUsers()
case Blank2 =>
val companyProfile = for {
company <- api.getCompany() // Future[Company]
location <- api.getLoc() // Future[Location]
} yield CompanyProfile(company, location)
companyProfile.map { cp =>
tranQ += cp.id -> cp.transaction // tranQ mutatated here
}
}
}
Since I am mutating the tranQ with futures, is this safe?
It is my understanding that each actor message is handled in a serial fashion, so although maybe frowned upon I can use mutable state like this.
I am just confused if using it inside of a future call like tranQ is safe or not.
No, your code is not safe.
While an actor processes one message at a time, you will lose this guarantee as soon as Futures are involed. At that point, the code inside the Future is executed on a (potentially) different thread and the next message might be handled by the actor.
A typical pattern to work around this issue is to send a message with the result of the Future using the pipeTo pattern, like so:
import akka.pattern.pipe
def receive: Receive {
case MyMsg =>
myFutureOperation()
.map(res => MyMsg2(res))
.pipeTo(self)
case MyMsg2(res) =>
// do mutation now
}
More information about using Futures can be found in akka's documentation: http://doc.akka.io/docs/akka/2.5/scala/futures.html

akka unstashAll not working

I am implementing an actor with multiple states and using Stash not to lose any messages. My states are initializing (get something from DB), running (handling requests) and updating (updating my state).
My problem is that I lose the messages when i try to unstashAll() in future resolving.
def initializing: Receive = {
case Initialize =>
log.info("initializing")
(for {
items1 <- db.getItems("1")
items2 <- db.getItems("2")
} yield items1 ::: items2) map {items =>
unstashAll()
context.become(running(items))
}
case r =>
log.debug(s"actor received message: $r while initializing and stashed it for further processing")
stash()}
i fixed it by changing my implementation to this
def initializing: Receive = {
case Initialize =>
log.info("initializing")
(for {
items1 <- db.getItems("1")
items2 <- db.getItems("2")
} yield items1 ::: items2) pipeTo self
context.become({
case items: List[Item] =>
unstashAll()
context.become(running(items))
case r =>
log.debug(s"actor received message: $r while initializing and stashed it for further processing")
stash()
})
case r =>
log.debug(s"actor received message: $r while initializing and stashed it for further processing")
stash()}
can anyone explain why the first didn't work ?
I think the unstashAll part works fine. The problem is that you were running it - together with your context.become - as part of a future callback.
This means that the code inside your map block escapes the predictability of your actor sequential processing. In other words, this could happen:
you call unstashAll
your messages are put back in the actor's mailbox
the actor picks up your messages one by one. The context still hasn't changed, so they are stashed again
your context finally becomes running (but it's too late)
The solution is - as you found out - the pipeTo pattern, which essentially sends a Futures result to the actor as a message. This makes it all sequential and predictable.

Twitter's "effective scala" broker example and tail recursion

In the document "Effective Scala" published by twitter, I see a code example:
class Pool(conns: Seq[Conn]) {
private[this] val waiters = new Broker[Conn]
private[this] val returnConn = new Broker[Conn]
val get: Offer[Conn] = waiters.recv
def put(c: Conn) { returnConn ! c }
private[this] def loop(connq: Queue[Conn]) {
Offer.choose(
if (connq.isEmpty) Offer.never else {
val (head, rest) = connq.dequeue
waiters.send(head) { _ => loop(rest) }
},
returnConn.recv { c => loop(connq enqueue c) }
).sync()
}
loop(Queue.empty ++ conns)
}
The code doesn't appear to be tail recursive, and isn't annotated as such. Since this is a connection pool that would presumably be left running for the life of the program, what would prevent a pool like this from eventually blowing up the stack, and generating a StackOverflowException?
The code is not recursive at all! loop does not call itself. It passes closures { _ => loop(rest) } and { c => loop(connq enqueue c) } to waiters.send and returnConn.recv respectively which call loop again. No recursion hence no stack overflow.

Simple Scala actor question

I'm sure this is a very simple question, but embarrassed to say I can't get my head around it:
I have a list of values in Scala.
I would like to use use actors to make some (external) calls with each value, in parallel.
I would like to wait until all values have been processed, and then proceed.
There's no shared values being modified.
Could anyone advise?
Thanks
There's an actor-using class in Scala that's made precisely for this kind of problem: Futures. This problem would be solved like this:
// This assigns futures that will execute in parallel
// In the example, the computation is performed by the "process" function
val tasks = list map (value => scala.actors.Futures.future { process(value) })
// The result of a future may be extracted with the apply() method, which
// will block if the result is not ready.
// Since we do want to block until all results are ready, we can call apply()
// directly instead of using a method such as Futures.awaitAll()
val results = tasks map (future => future.apply())
There you go. Just that.
Create workers and ask them for futures using !!; then read off the results (which will be calculated and come in in parallel as they're ready; you can then use them). For example:
object Example {
import scala.actors._
class Worker extends Actor {
def act() { Actor.loop { react {
case s: String => reply(s.length)
case _ => exit()
}}}
}
def main(args: Array[String]) {
val arguments = args.toList
val workers = arguments.map(_ => (new Worker).start)
val futures = for ((w,a) <- workers zip arguments) yield w !! a
val results = futures.map(f => f() match {
case i: Int => i
case _ => throw new Exception("Whoops--didn't expect to get that!")
})
println(results)
workers.foreach(_ ! None)
}
}
This does a very inexpensive computation--calculating the length of a string--but you can put something expensive there to make sure it really does happen in parallel (the last thing that case of the act block should be to reply with the answer). Note that we also include a case for the worker to shut itself down, and when we're all done, we tell the workers to shut down. (In this case, any non-string shuts down the worker.)
And we can try this out to make sure it works:
scala> Example.main(Array("This","is","a","test"))
List(4, 2, 1, 4)

How can Scala actors return a value in response to a message?

There are plenty of examples of actors replying with another message back to the sender, but whilst browsing the API docs I noticed the !! and !? operators which are part of the CanReply trait (which seems to be new to 2.8: http://www.scala-lang.org/archives/rc-api/scala/actors/CanReply.html). I was therefore wondering whether it was just a case of having the receive/react block return a value, i.e. make the PartialFunction return type something other than Unit?
I'll start digging through the source to try to work out how they're meant to be used, but if anyone has any insight or knows of any more in-depth documentation or examples then I'd be most grateful.
Cheers,
Paul.
Replies can be sent with the method reply, as shown here:
import scala.actors._
class Reverser extends Actor {
def act() { Actor.loop { react {
case s: String => Thread.sleep(1000); reply(s.reverse)
case _ => exit()
}}}
}
There are three ways to explicitly accept the reply.
Use !!, which returns a Future, which is a container class that promises to give you the contents when you need them. It returns immediately, but if you actually ask for the contents, you have to wait until the other thread is done and fills the request.
Use !? without a timeout. Your code will pause for as long as it takes for the other thread to reply.
Use !? with a timeout. Your code will pause until it gets a reply or until the timeout expires, whichever comes first.
Here's an example of all three:
val r = new Reverser
r.start
val a = (r !! "Hi")
a() match {
case s: String => println(s)
case _ => println("Error A")
}
val b = r !? "Hello"
b match {
case s: String => println(s)
case _ => println("Error B")
}
val c = (r !? (500,"Howdy"))
c match {
case Some(s: String) => println(s)
case Some(_) => println("Error C")
case None => println("Too slow!")
}
r ! None // None isn't a string, so r will stop running
And if you run this you get
iH
elloH
Too slow!