This page is no longer maintained — Please continue to the home page at www.scala-lang.org

[newbie] Question about actor concurrency?

3 replies
Rogelio
Joined: 2009-04-27,
User offline. Last seen 42 years 45 weeks ago.

Hi ... scala newbie with a question on actors and concurrency. I've been
reading
several articles and tutorials but haven't understood how to answer my own
question and
a search of this archive did not reveal an answer that seemed to apply ...

I'm considering using scala as a backend option to a web/database app. The
web page
would allow the user to request a PDF report. Since that will be a long
running process
I want to pass that off to a scala program. But I also don't want to
process the PDF reports
one at a time, because if 100 people request a PDF, then they could end up
waiting
30+ minutes for results.

If I have some sort of:

loop {
react {
case .... create_the_pdf(user)
}
}

is that all that is needed? I mean if 100 people request a PDF and I send
100 messages to this
actor to create the pdf, will it automatically spawn off 100 copies of
itself to process simultaneously?

Related, if I only wanted to process say 20 PDFs at a time (to avoid using
up system resources), how
does one limit the processing to 20 a time for example?

Thanks for you time and patience.

Rogelio

Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [newbie] Question about actor concurrency?
If an actor is blocked by a time consuming blocking operation it is blocked... no matter if it's a loop-react (I find the name thread-less quite unfortunate) or while-receive type actor.

It's easy to be checked with:

import scala.actors._
import Actor._

val a = actor { loop { react {
     |   case msg => println("starting"); Thread.sleep(2000); println("done"); reply(msg);
     | }}}
a: scala.actors.Actor = scala.actors.Actor$$anon$1@1eb8f71

a ! 1; a ! 2; a ! 3 

You can either make the bocking operation more granular so parts of it can be done by separate actors in parrallel or make copies of the executor actor to make use of all the cores... because obiously, if the target machine isn't capable of doing things in parallel you won't get anything.

To create multiple copies of an executor actor I like to clone them like this

val archetype = actor { loop { react { ... } } }
val pool = 8 * archetype

See my blogpost to see how to implement the magic multiply operator http://dzhigital.blogspot.com/2009/03/cloning-scala-actors.html

You can then create an actor that will just load balance the work between them and forward the messages in a round-robin fashion.

Szymon

On Mon, Apr 27, 2009 at 8:42 PM, Rogelio <rogboone@yahoo.com> wrote:

Hi ... scala newbie with a question on actors and concurrency.  I've been
reading
several articles and tutorials but haven't understood how to answer my own
question and
a search of this archive did not reveal an answer that seemed to apply ...

I'm considering using scala as a backend option to a web/database app.  The
web page
would allow the user to request a PDF report.  Since that will be a long
running process
I want to pass that off to a scala program.  But I also don't want to
process the PDF reports
one at a time, because if 100 people request a PDF, then they could end up
waiting
30+ minutes for results.

If I have some sort of:

loop {
 react {
     case .... create_the_pdf(user)
 }
}

is that all that is needed?  I mean if 100 people request a PDF and I send
100 messages to this
actor to create the pdf, will it automatically spawn off 100 copies of
itself to process simultaneously?

Related, if I only wanted to process say 20 PDFs at a time (to avoid using
up system resources),  how
does one limit the processing to 20 a time for example?

Thanks for you time and patience.

Rogelio
--
View this message in context: http://www.nabble.com/-newbie--Question-about-actor-concurrency--tp23262503p23262503.html
Sent from the Scala - User mailing list archive at Nabble.com.




--
ʎɐqǝ uo pɹɐoqʎǝʞ ɐ ʎnq ı ǝɯıʇ ʇsɐן ǝɥʇ sı sıɥʇ
DRMacIver
Joined: 2008-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: [newbie] Question about actor concurrency?

2009/4/28 Szymon Jachim :
> If an actor is blocked by a time consuming blocking operation it is
> blocked... no matter if it's a loop-react (I find the name thread-less quite
> unfortunate) or while-receive type actor.
>
> It's easy to be checked with:
>
> import scala.actors._
> import Actor._
>
> val a = actor { loop { react {
>      |   case msg => println("starting"); Thread.sleep(2000);
> println("done"); reply(msg);
>      | }}}
> a: scala.actors.Actor = scala.actors.Actor$$anon$1@1eb8f71
>
> a ! 1; a ! 2; a ! 3
>
> You can either make the bocking operation more granular so parts of it can
> be done by separate actors in parrallel or make copies of the executor actor
> to make use of all the cores... because obiously, if the target machine
> isn't capable of doing things in parallel you won't get anything.
>
> To create multiple copies of an executor actor I like to clone them like
> this
>
> val archetype = actor { loop { react { ... } } }
> val pool = 8 * archetype
>
> See my blogpost to see how to implement the magic multiply operator
> http://dzhigital.blogspot.com/2009/03/cloning-scala-actors.html
>

That looks rather needlessly magic and error prone compared to val
pool = List.range(0, 8).map{i => actor { loop { react { ... } } } }.

Szymon Jachim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [newbie] Question about actor concurrency?
FP allows to be so terse and put so much in one line but I'm not sure that I want to do it...
That said I won't protest against something like:

  def createPool(n: Int, a: => Actor) = List.range(0, n).map{ i => a }

  val pool = createPool(8, actor { })

Now is
  val pool = 8 * actor { }
really that less readable? :-)

Szymon


On Tue, Apr 28, 2009 at 10:22 AM, David MacIver <david.maciver@gmail.com> wrote:
2009/4/28 Szymon Jachim <sjachim@gmail.com>:
> If an actor is blocked by a time consuming blocking operation it is
> blocked... no matter if it's a loop-react (I find the name thread-less quite
> unfortunate) or while-receive type actor.
>
> It's easy to be checked with:
>
> import scala.actors._
> import Actor._
>
> val a = actor { loop { react {
>      |   case msg => println("starting"); Thread.sleep(2000);
> println("done"); reply(msg);
>      | }}}
> a: scala.actors.Actor = scala.actors.Actor$$anon$1@1eb8f71
>
> a ! 1; a ! 2; a ! 3
>
> You can either make the bocking operation more granular so parts of it can
> be done by separate actors in parrallel or make copies of the executor actor
> to make use of all the cores... because obiously, if the target machine
> isn't capable of doing things in parallel you won't get anything.
>
> To create multiple copies of an executor actor I like to clone them like
> this
>
> val archetype = actor { loop { react { ... } } }
> val pool = 8 * archetype
>
> See my blogpost to see how to implement the magic multiply operator
> http://dzhigital.blogspot.com/2009/03/cloning-scala-actors.html
>

That looks rather needlessly magic and error prone compared to val
pool = List.range(0, 8).map{i => actor { loop { react { ... } } } }.



--
ʎɐqǝ uo pɹɐoqʎǝʞ ɐ ʎnq ı ǝɯıʇ ʇsɐן ǝɥʇ sı sıɥʇ

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland