PicoThreads: Lightweight Threads in Java Andrew Begel, Josh MacDonald, Michael Shilman [abegel, jmacd, michaels]@cs.berkeley.edu Department of Electrical Engineering & Computer Sciences University of California, Berkeley, CA 94720 Abstract High-performance, I/O-intensive applications often require complicated, split-phase, event-based implementations. Threads appear to be an attractive alternative because they allow the programmer to write a single sequence of operations and ignore the points at which the execution may be blocked. Unfor- tunately, the typical amount of memory required to support this technique prevents applications from scaling to large numbers of threads. Rather than relying on event-based programming, we use a program transformation to provide a low- cost thread implementation. This transformation retains the advantages of user-scheduled, event- based programs, yet efficiently supports large num- bers of threads. We replace the standard Java thread mechanism with lightweight PicoThreads and a coop- erative, event-based, user-level scheduler. This is accompanied by a PicoThread-aware, asynchronous network library. To evaluate our implementation, we measure the performance of a simple web crawler running thousands of threads. Our results show that PicoThreaded programs per- form comparably or substantially better than threaded programs when using large numbers of threads. 1 Introduction Threads evolved out of the operating system commu- nity as a general-purpose solution for implementing concurrent systems. Concurrency is often used by the operating system to efficiently overlap computation with concurrent, blocking requests. Threads, how- ever, are not ideally suited for this purpose. Indeed, Ousterhout suggests that threads are seldom a good idea and proposes event-based programming as a bet- ter alternative [O96]. 1.1 Event-Based Programming vs. Thread Programming Event-driven or event-based programs are those which handle these situations by registering handlers to respond to various events. In this technique, code to handle a blocking call first initiates an asynchro- nous request, and then registers a callback method to complete the computation when the request has com- pleted. This implementation strategy does not require threads or synchronization (on a uni-processor), and leads to efficient, user-schedulable programs with lit- tle support from the operating system. Event-based programs are popular for implementing graphical user interfaces and are also used to handle large-scale network services where events correspond to the completion of an I/O request or the arrival of a new connection. While the advantages seem clear, event-based pro- gramming is not always the right answer. Threaded programming allows the programmer to write a logi- cally sequential program, whereas event-based pro- grams require the programmer to carefully divide each sequence of operations into non-blocking han- dlers that maintain persistent state. What began as a simple block of code degenerates into a much larger body of code which is often difficult to read, write and maintain. System threads also provide the illusion of concurrency on a uniprocessor 1 . However, the reason that event-based programming is popular is because it solves a large class of problems which do not require true concurrency. Using threads to handle overlapping, blocking requests is often more complicated and costly than necessary. In par- ticular, synchronization, locking and preemptive scheduling are not always needed, but the thread pro- grammer must accept all three and pay the cost in debugging difficulty as well. For a program running 1. Or actual concurrency when multiple processors are available