610 likes | 662 Vues
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.
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