610 likes | 669 Views
Uncover errors in actor-based programs with a focus on concurrency models, message passing, behavior, and synchronization methods. Learn from real-world applications and examples. Discover the nuances of processing messages and maintaining synchronization in actor systems. Explore the expected message schedule and behaviors. Dive into the complexities and advantages offered by the actor model.
E N D
Searching for Errors in Actor-based Programs Steven Lauterburg University of Illinois at Urbana-Champaign
Concurrency • Growing use of multi-core systems and increased emphasis on parallelism and concurrency in application development. • Increased focus on concurrency based on shared memory models. • Notoriously difficult to get right • Common problems include data races, atomicity violations, deadlocks University of Illinois at Urbana-Champaign
Data Race Example X = 0 Thread 2 Thread 1 a = X a = X a = a + 1 a = a + 1 X = a X = a X = ??? University of Illinois at Urbana-Champaign
Actor Model • Actor Model offers an alternative based on message passing • Not just multicore systems… • distributed systems • “super” computers • cloud computing • sensor networks • etc. University of Illinois at Urbana-Champaign
Actor Model • Increasing number of actor languages and libraries: ActorFoundry, AmbientTalk, Axum, Charm++, E, Erlang, Jetlang, Kilim, Newspeak, Ptolemy II, Revactor, ThAL, SALSA, Scala, Singularity, Asynchronous Agents Framework (Microsoft Visual Studio 2010)… • Real-world applications: Twitter’s message queuing system, Lift Web Framework, Facebook’s chat system, Vendetta’s game engine… University of Illinois at Urbana-Champaign
What are Actors? Actor Components… • Behavior • State • Independent thread of control • Mail queue • Unique name allows mobility and location transparency! University of Illinois at Urbana-Champaign
Actor Message Processing Processing messages… • Send messages • Create new actors • Update local state • Change data • Change behavior University of Illinois at Urbana-Champaign
Actor Model Semantics • Actors do not share state! Actors communicate with each other only using (asynchronous, non-blocking) messages. • The actor model does not guarantee in-order delivery of messages… but does assume that message will eventually be delivered • Actors process only one message at a time… access is serialized. • The execution of actor code from receipt of a message until immediately before the receipt of the next message can be viewed as atomic. This atomic execution of code is called a “macro-step” • Non-determinism is a result of message delivery order… not the ordering of shared memory accesses. University of Illinois at Urbana-Champaign
Actor Model Synchronization University of Illinois at Urbana-Champaign
Actor Model Synchronization • RPC-like Messaging • “The sender of a message waits for a reply before processing other messages” University of Illinois at Urbana-Champaign
Actor Model Synchronization • RPC-like Messaging • “The sender of a message waits for a reply before processing other messages” • Client sends a request • Client checks incoming messages • If the message is the expected reply, the message is processed • If the message is not the expected reply, it must be buffered for future processing, and the client continues to check incoming messages University of Illinois at Urbana-Champaign
Actor Model Synchronization • Local Synchronization Constraints: • Actors can determine which messages they will process using by considering the state of the actor and the type of a message delivered to its mailbox. • For Example: • ActorFoundry uses logical formulas (encoded as Java methods) to determine if a message should be processed • Scala and Erlang use pattern matching to do the same University of Illinois at Urbana-Champaign
Example – Simple Client and Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } Based on an actor application written in Scala from the ScalaWiki website. http://scala.sygneca.com/ University of Illinois at Urbana-Champaign
Example – Simple Client and Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Expected Message Schedule Expected Behavior! ------ v1 = v2 v1=1 v2=1 Client get kill get ret(1) ret(0) set(1) Server value=1 Creation and Delivery of Messages over Time University of Illinois at Urbana-Champaign
Expected Message Schedule Expected Behavior! ------ v1 = v2 v1=1 v2=1 Client get kill get ret(1) ret(0) set(1) Server value=1 This example also has several other message schedules, some of which lead to incorrect behaviors! University of Illinois at Urbana-Champaign
Example – Simple Client & Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Example – State Space 6 message schedules 26 states 20 different states University of Illinois at Urbana-Champaign
Example – State Space 6 message schedules 26 states 20 different states University of Illinois at Urbana-Champaign
Example – State Space 6 message schedules 26 states 20 different states An assertion violation University of Illinois at Urbana-Champaign
Example – Message Schedule Assertion violation ------ v1 ≠ v2 v1=0 v2=1 Client get kill get set(1) ret(1) ret(0) Server value=1 University of Illinois at Urbana-Champaign
Example – Simple Client & Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Example – Simple Client & Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Example – Simple Client & Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Example – State Space 6 message schedules 26 states 20 different states An undeliverable message University of Illinois at Urbana-Champaign
Example – Message Schedule v1=0 v2=0 Client get kill set(1) ret(0) ret(0) get Server Undeliverable message University of Illinois at Urbana-Champaign
Example – Simple Client & Server Class Server extends Actor { int value = 0; @message void set(int v) {value = v} @message int get() {return value;} @message void kill() {destroy("server is done");} } Class Client extends Actor { @message void start() { ActorName server = createActor(Server.class); send(server, "set", 1); int v1 = call(server, "get"); int v2 = call(server, "get"); assert(v1 == v2); send(server, "kill"); } } University of Illinois at Urbana-Champaign
Example 2 – Divide & Conquer Master (Map) Master (Reduce) Worker #1 Worker #2 Worker #N … University of Illinois at Urbana-Champaign
Example 3 – Deadlock call(B, "get"); B A University of Illinois at Urbana-Champaign
Example 3 – Deadlock call(B, "get"); B A call(A, “query"); University of Illinois at Urbana-Champaign
So How Do We Test Actors? Testing the possible behaviors of an actor program requires us to systematically explore the different message delivery schedules. University of Illinois at Urbana-Champaign
State-Space Exploration • State-space exploration (SSE) is the basis for systematic testing (program model checking). • Identification of errors. • Verification of desired properties. • Systematic exploration of a program’s state space. • Research and tools focused on exploring the behavior of shared-memory programs. • e.g., Chess[Musuvathi & Qadeer, 2007], Java PathFinder [Visseret al., 2000] University of Illinois at Urbana-Champaign
Systematic Testing for Actors Challenges: • Existing approaches/tools are focused on exploration of multi-threaded programs using shared-memory. University of Illinois at Urbana-Champaign
Systematic Testing for Actors Challenges: • Existing approaches/tools are focused on exploration of multi-threaded programs using shared-memory. • Complex multi-threaded runtime architectures underlie user actor code. University of Illinois at Urbana-Champaign
ActorFoundry Architecture TCP, UDP Broker, Shell University of Illinois at Urbana-Champaign
Exploring Scala Actor Code • Exploring a simple actor program written in Scala using Java PathFinder: • Simple “HelloWorld” program University of Illinois at Urbana-Champaign
Exploring Scala Actor Code • Exploring a simple actor program written in Scala using Java PathFinder: • Simple “HelloWorld” program • Without modification to the Scala library or architecture exploration did not finish after running for over an hour. • With some modification (e.g., reduced thread pool size, etc.) exploration still took over 7 minutes. University of Illinois at Urbana-Champaign
Systematic Testing for Actors Challenges: • Existing approaches/tools are focused on exploration of multi-threaded programs using shared-memory. • Complex multi-threaded runtime architectures underlie user actor code. • Development of separate tools for different (yet similar) languages/libraries is costly, requiring complex algorithms to be reimplemented for each actor system. University of Illinois at Urbana-Champaign
Basset Provides an efficient systematic testing framework for Java-based actor programs • Supports exploration of actor application code itself, not the actor libraries and runtime architectures. • Allows dynamic, direct exploration of unmodified application code. • Leverages actor semantics to allow efficient exploration. • Facilitates reuse of capabilities across multiple languages and libraries, specifically those that target Java bytecode, though not necessarily the Java language. • Currently we support ActorFoundry and Scala University of Illinois at Urbana-Champaign
The Basset Framework Actor Programs Adapter Basset Core Java PathFinder University of Illinois at Urbana-Champaign
Actor Programs Adapter Basset Core Java PathFinder Architecture – Actor Programs • Developed normally in the supported language (e.g., Scala, ActorFoundry). • No source code changes are necessary for Basset to explore the programs. • Tester needs to code a simple test driver University of Illinois at Urbana-Champaign
Example Driver class Driver extends Actor { public static void main(String[] args) { explore(); } public static void explore() { // create rootset actors ActorName server = FrameUtil.createActor(Server.class); ActorName client = FrameUtil.createActor(Client.class, server); // initialize actors FrameUtil.send(client, “start”); } } University of Illinois at Urbana-Champaign
Actor Programs Adapter Basset Core Java PathFinder Architecture – Adapter • Created for each language supported. • Preserves the library API for the application code. • A significantly slimmed down version of the library that redirects operations to Basset. University of Illinois at Urbana-Champaign
ActorFoundry Adapter To create the ActorFoundry adapter: • 6 existing classes were modified (out of 100+): Actor, ActorImpl, ActorMsgRequest, ActorName, BasicActorImpl, and DeepCopy • 2 new classes were created: ActorMessage and FoundryItemsFactory University of Illinois at Urbana-Champaign
Actor Programs Adapter Basset Core Java PathFinder Architecture – The Basset Core • Manages overall exploration of possible message delivery schedules. • Supports state assertions, undeliverable message and deadlock detection, etc. • Facilitates the reuse of capabilities across multiple languages. University of Illinois at Urbana-Champaign
Actor Programs Adapter Basset Core Java PathFinder Architecture – Java PathFinder • Performs actual bytecode execution. • Facilitates nondeterministic choices and thread management • Provides state saving, restoring and backtracking. University of Illinois at Urbana-Champaign
Results: Framework Efficiency • Exploring actor program using Java PathFinder • Simple “HelloWorld” program • Without modification to Scala library or architecture exploration did not finish after running for over an hour. • With some modification (e.g., reduced thread pool size, etc.) exploration took over 7 minutes. University of Illinois at Urbana-Champaign
Results: Framework Efficiency • Exploring actor program using Java PathFinder • Simple “HelloWorld” program • Without modification to Scala library or architecture exploration did not finish after running for over an hour. • With some modification (e.g., reduced thread pool size, etc.) exploration took over 7 minutes. • Exploring the same actor program using the Scala instantiation of Basset • Exploration took less than one second. University of Illinois at Urbana-Champaign
Experiments: State-Space Exploration Note: Times are for Scala programs using the Basset instantiation for Scala. University of Illinois at Urbana-Champaign
Can we do better? Basset Efficiency University of Illinois at Urbana-Champaign