Successfully reported this slideshow.
Your SlideShare is downloading. ×

Actor Concurrency

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Java Concurrency Idioms
Java Concurrency Idioms
Loading in …3
×

Check these out next

1 of 63 Ad

Actor Concurrency

Download to read offline

An introduction to Erlang and the actor model of concurrency.

Author: Alex Miller
Blog: http://tech.puredanger.com
Twitter: @puredanger

An introduction to Erlang and the actor model of concurrency.

Author: Alex Miller
Blog: http://tech.puredanger.com
Twitter: @puredanger

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to Actor Concurrency (20)

Advertisement

More from Alex Miller (20)

Recently uploaded (20)

Advertisement

Actor Concurrency

  1. 1. Actor Concurrency Alex Miller Blog: http://tech.puredanger.com Twitter: @puredanger
  2. 2. 8086
  3. 3. Moore’s Law? http://en.wikipedia.org/wiki/CPU_speed http://en.wikipedia.org/wiki/Transistor_count
  4. 4. Moore’s Law? http://en.wikipedia.org/wiki/CPU_speed http://en.wikipedia.org/wiki/Transistor_count
  5. 5. Moore’s Law? http://en.wikipedia.org/wiki/CPU_speed http://en.wikipedia.org/wiki/Transistor_count
  6. 6. State of the Practice public class Counter { private int count = 0; public int increment() { synchronized(this) { return ++count; } } }
  7. 7. JCIP says: • It’s the mutable state, stupid. • Make fields final unless they need to be mutable. • Immutable objects are automatically thread-safe. • Encapsulation makes it practical to manage the complexity. • Guard each mutable variable with a lock. • Guard all variables in an invariant with the same lock. • Hold locks for the duration of compound actions. • A program that accesses a mutable variable from multiple threads without synchronization is a broken program. • Don’t rely on clever reasoning about why you don’t need to synchronize. • Include thread safety in the design process - or explicitly document that your class is not thread-safe. • Document your synchronization policy.
  8. 8. JCIP says: • It’s the mutable state, stupid. • Make fields final unless they need to be mutable. • Immutable objects are automatically thread-safe. • Encapsulation makes it practical to manage the complexity. • Guard each mutable variable with a lock. • Guard all variables in an invariant with the same lock. • Hold locks for the duration of compound actions. • A program that accesses a mutable variable from multiple threads without synchronization is a broken program. • Don’t rely on clever reasoning about why you don’t need to synchronize. • Include thread safety in the design process - or explicitly document that your class is not thread-safe. • Document your synchronization policy.
  9. 9. The problem with shared state concurrency
  10. 10. The problem with shared state concurrency ...is the shared state.
  11. 11. Actors • No shared state • Lightweight processes • Asynchronous message-passing • Buffer messages in a mailbox • Receive messages with pattern matching
  12. 12. The Basics
  13. 13. The Basics spawn
  14. 14. The Basics send spawn
  15. 15. The Basics receive
  16. 16. Erlang • Invented at Ericsson • Functional language • Dynamic typing • Designed for concurrency, fault-tolerance
  17. 17. Single assignment Eshell V5.6.3 (abort with ^G) 1> A = 4. 4 2> A. 4 3> A = 6. ** exception error: no match of right hand side value 6 4> A = 2*2. 4
  18. 18. Atoms and Tuples 1> F=foo. foo 2> Stooges = {larry,curly,moe}. {larry,curly,moe} 3> Me = {person,quot;Alexquot;,quot;nachosquot;}. {person,quot;Alexquot;,quot;nachosquot;} 4> {person,Name,Food} = Me. {person,quot;Alexquot;,quot;nachosquot;} 5> Name. quot;Alexquot; 6> Food. quot;nachosquot;
  19. 19. Lists 1> List=[1,2,3]. [1,2,3] 2> [First|Rest]=List. [1,2,3] 3> First. 1 4> Rest. [2,3] 5> List2=[4|List]. [4,1,2,3] 6> [Char|String] = “abc”. “abc” 7> Char. 97
  20. 20. Functions 1> Square = fun(X) -> X*X end. #Fun<erl_eval.6.13229925> 2> Square(5). 25. 3> TimesN = fun(N) -> (fun(X) -> N*X end) 3> end. #Fun<erl_eval.6.13229925> 4> lists:map(TimesN(10), [1,2,3]). [10,20,30]
  21. 21. Modules -module(mymath). -export([square/1,fib/1]). square(Value) -> Value*Value. fib(0) -> 0; fib(1) -> 1; fib(N) when N>0 -> fib(N-1) + fib(N-2). 1> c(mymath.erl). 2> mymath:square(5). 25 3> mymath:fib(7). 13
  22. 22. Modules and Functions -module(mymath2). -export([fibtr/1]). fibtr(N) -> fibtr_iter(N, 0, 1). fibtr_iter(0, Result, _Next) -> Result; fibtr_iter(Iter, Result, Next) when Iter > 0 -> fibtr_iter(Iter-1, Next, Result+Next). 1> c(mymath2.erl). 2> mymath2:fibtr(200). 280571172992510140037611932413038677189525
  23. 23. Concurrency Primitives • Pid = spawn(fun) • Pid ! message • receive...end
  24. 24. Concurrency Primitives • Pid = spawn(fun) • Pid ! message • receive...end Pid
  25. 25. Concurrency Primitives • Pid = spawn(fun) • Pid ! message • receive...end Pid
  26. 26. Concurrency Primitives • Pid = spawn(fun) • Pid ! message • receive...end Pid
  27. 27. Concurrency Primitives • Pid = spawn(fun) • Pid ! message • receive...end receive Pid ... end
  28. 28. A Simple Process loop() -> receive {toF, C} -> io:format(quot;~p C is ~p F~nquot;, [C, 32+C*9/5]), loop(); {toC, F} -> io:format(quot;~p F is ~p C~nquot;, [F, (F-32)*5/9]), loop(); {stop} -> io:format(quot;Stopping~nquot;); Other -> io:format(quot;Unknown: ~p~nquot;, [Other]), loop() end.
  29. 29. Spawn! 1> c(temperature). {ok,temperature} 2> Pid = spawn(fun temperature:loop/0). <0.128.0> 3> Pid ! {toC, 32}. 32F is 0.0 C {convertToC,32} 4> Pid ! {toF, 100}. 100C is 212.0 F {convertToF,100} 5> Pid ! {stop}. Stopping {stop}
  30. 30. Responding -module(temp2). -export([start/0,convert/2]). start() -> spawn(fun() -> loop() end). convert(Pid, Request) -> Pid ! {self(), Request}, receive {Pid, Response} -> Response end.
  31. 31. Responding loop() -> receive {From, {toF, C}} -> From ! {self(), 32+C*9/5}, loop(); {From, {toC, F}} -> From ! {self(), (F-32)*5/9}, loop(); {From, stop} -> From ! {self(), stop}, io:format(quot;Stopping~nquot;); {From, Other} -> From ! {self(), {error, Other}}, loop() end.
  32. 32. Responding 1> c(temp2). {ok,temp2} 2> Pid = temp2:start(). <0.57.0> 3> temp2:convert(Pid2, {toF, 100}). 212.0
  33. 33. Process Ring
  34. 34. Running Rings 1> c(ring). 2> T=ring:startTimer(). 3> R=ring:startRing(100,T). spawned 100 in 241 microseconds 4> R ! start. {1230,863064,116530} Starting message {1230,863064,879862} Around ring 10000 times {1230,863065,642097} Around ring 20000 times ...etc {1230,863140,707023} Around ring 990000 times {1230,863141,471193} Around ring 1000000 times Start={1230,863064,116875} Stop={1230,863141,471380} Elapsed=77354505 5> R20k = ring:startRing(20000,T). spawned: 20000 in 118580 microseconds
  35. 35. Processes and Messages • Processes cheap to create (10ks < second) • Create many processes (10ks to 100ks) • Messages very fast to send (1M / second)
  36. 36. Error Handling
  37. 37. Error Handling link
  38. 38. Error Handling link
  39. 39. Error Handling exit signal
  40. 40. Linked Processes reportExit(WatchedPid) -> spawn(fun() -> process_flag(trap_exit, true), link(WatchedPid), receive {'EXIT', _Pid, Msg} -> io:format(quot;got linked exit: ~p~nquot;, [Msg]) end end). startWatched() -> spawn(fun() -> receive die -> exit(quot;diequot;); crash -> erlang:error(quot;crashquot;) end end).
  41. 41. Linked Processes 1> c(link). 2> P1 = link:startWatched(). 3> P2 = link:startWatched(). 4> link:reportExit(P1). 5> link:reportExit(P2). 6> P1 ! die. got linked exit: quot;diequot; 7> P2 ! crash. got linked exit: {quot;crashquot;,[{link,'- startWatched/0-fun-0-',0}]}
  42. 42. Does it work?
  43. 43. Ericsson AXD301 • Telecom ATM switch • Millions of calls / week • 99.9999999% uptime = 32 ms down / year • -> Nortel Alteon SSL Accelerator
  44. 44. YAWS http://www.sics.se/~joe/apachevsyaws.html
  45. 45. Messaging
  46. 46. Facebook Chat “For Facebook Chat, we rolled our own subsystem for logging chat messages (in C++) as well as an epoll- driven web server (in Erlang) that holds online users' conversations in-memory and serves the long-polled HTTP requests. Both subsystems are clustered and partitioned for reliability and efficient failover. ” Reference: http://www.facebook.com/note.php?note_id=14218138919
  47. 47. And others...
  48. 48. • JVM-based language • Object-functional hybrid • Actor library
  49. 49. Scala Rings def act() { loop { react { case StartMessage => { log(quot;Starting messagesquot;) timer ! StartMessage nextNode ! TokenMessage(nodeId, 0) } case StopMessage => { log(quot;Stoppingquot;) nextNode ! StopMessage exit }
  50. 50. Scala Rings case TokenMessage(id,value) if id == nodeId => { val nextValue = value+1 if(nextValue % 10000 == 0) log(quot;Around ring quot; + nextValue + quot; timesquot;) if(nextValue == 1000000) { timer ! StopMessage timer ! CancelMessage nextNode ! StopMessage exit } else { nextNode ! TokenMessage(id, nextValue) } } case TokenMessage(id,value) => { nextNode ! TokenMessage(id,value) } }
  51. 51. Comparison to Erlang • receive-based actors cheap to create (Erlang about 3x faster) • Can also create many processes • Messages also fast to send (Erlang about 2x faster)
  52. 52. • Java-based framework with compile-time weaving • Tasks - lightweight threads/processes/etc • @pausable - let task be paused during execution • sleep / yield • Mailbox (typed via generics) - single consumer • Messaging - mutable (in limited ways)
  53. 53. Kilim Ring import kilim.Mailbox; import kilim.Task; import kilim.pausable; public class NodeActor extends Task { private final int nodeId; private final Mailbox<Message> inbox; private final Mailbox<Message> timerInbox; private Mailbox<Message> nextInbox; public NodeActor(int nodeId, Mailbox<Message> inbox, Mailbox<Message> timerInbox) { this.nodeId = nodeId; this.inbox = inbox; this.timerInbox = timerInbox; }
  54. 54. Kilim Ring @pausable public void execute() throws Exception { while(true) { Message message = inbox.get(); if(message.equals(Message.START)) { timerInbox.putnb(Message.START); nextInbox.putnb(new TokenMessage(nodeId, 0)); } else if(message.equals(Message.STOP)) { nextInbox.putnb(Message.STOP); break; ...
  55. 55. Kilim Ring } else if(message instanceof TokenMessage) { TokenMessage token = (TokenMessage)message; if(token.source == nodeId) { int nextVal = token.value+1; if(nextVal == 1000000) { timerInbox.putnb(Message.STOP); timerInbox.putnb(Message.CANCEL); nextInbox.putnb(Message.STOP); break; } else { token.value = nextVal; nextInbox.putnb(token); } } else { nextInbox.putnb(token); } } }
  56. 56. Performance 10.0 400 7.5 300 milliseconds milliseconds 5.0 200 2.5 100 0 0 100 nodes 20k nodes 130,000 Erlang 97,500 milliseconds Scala Kilim 65,000 32,500 0 100M messages
  57. 57. http://tech.puredanger.com/presentations/actor-concurrency

×