An Efficient Implementation of Guard-Based Synchronization for an Object-Oriented Programming Language an Efficient Implementation of Guard-Based
Total Page:16
File Type:pdf, Size:1020Kb
AN EFFICIENT IMPLEMENTATION OF GUARD-BASED SYNCHRONIZATION FOR AN OBJECT-ORIENTED PROGRAMMING LANGUAGE AN EFFICIENT IMPLEMENTATION OF GUARD-BASED SYNCHRONIZATION FOR AN OBJECT-ORIENTED PROGRAMMING LANGUAGE By SHUCAI YAO, M.Sc., B.Sc. A Thesis Submitted to the Department of Computing and Software and the School of Graduate Studies of McMaster University in Partial Fulfilment of the Requirements for the Degree of Doctor of Philosophy McMaster University c Copyright by Shucai Yao, July 2020 Doctor of Philosophy (2020) McMaster University (Computing and Software) Hamilton, Ontario, Canada TITLE: An Efficient Implementation of Guard-Based Synchro- nization for an Object-Oriented Programming Language AUTHOR: Shucai Yao M.Sc., (Computer Science) University of Science and Technology Beijing B.Sc., (Computer Science) University of Science and Technology Beijing SUPERVISOR: Dr. Emil Sekerinski, Dr. William M. Farmer NUMBER OF PAGES: xvii,167 ii To my beloved family Abstract Object-oriented programming has had a significant impact on software development because it provides programmers with a clear structure of a large system. It encap- sulates data and operations into objects, groups objects into classes and dynamically binds operations to program code. With the emergence of multi-core processors, application developers have to explore concurrent programming to take full advan- tage of multi-core technology. However, when it comes to concurrent programming, object-oriented programming remains elusive as a useful programming tool. Most object-oriented programming languages do have some extensions for con- currency, but concurrency is implemented independently of objects: for example, concurrency in Java is managed separately with the Thread object. We employ a programming model called Lime that combines action systems tightly with object- oriented programming and implements concurrency by extending classes with actions and guarded methods. This provides programmers with a unified and straightforward design view for a concurrent object-oriented program. In this work, using coroutines with guarded methods and actions is proposed as a means of implementing the concurrency extension for objects. Mapping objects to coroutines can result in stack overflow as the number of objects increases. A dy- namically segmented stack mechanism, which does not introduce runtime overhead, is implemented to support large-scale concurrency. Since Lime allows guarded meth- ods and actions to \get stuck," a new user-level cooperative scheduler, and a fast coroutine context switch mechanism are implemented to improve the performance. Compared with the traditional segmented stack mechanisms, the new dynamically segmented stack mechanism gets equal performance for more common scenarios. Be- sides, it outperforms the contemporary stack mechanisms for deep recursion scenarios. Above all, Lime does not only provide the programmers with a unified and straight- forward object-oriented programming model for concurrency, but also accomplishes a better performance than concurrent programming languages such as Erlang and Go, in fine-grained, highly concurrent benchmarks. iii Acknowledgements First and foremost, I would like to express my gratitude to my academic supervisor Dr. Emil Sekerinski for his unwavering support, invaluable guidance, and continuous encouragement throughout the development and advancement of my research studies. Secondly, I would like to express great appreciation to my co-supervisor, Dr. William M. Farmer, for his excellent comments and suggestions on my thesis and a careful review of the thesis. My special thanks go to the other members of my supervisory committee: Dr. Wolfram Kahl and Dr. Frantisek (Franya) Franek, for excellent comments and sug- gestions on supervisory committee meetings and a careful review of the thesis. I also appreciate the help and moral support from all of the other individuals whom I have interacted with throughout my graduate studies. Furthermore, I want to extend my sincere thanks to the China Scholarship Council, Global Water Futures and McMaster University graduate scholarship, which have provided financial support during my doctoral studies. Last, but certainly not least, I would like to thank my dear family and my fellow graduate students, Dr. Ronald Eden Burton, Dr. Bojan Nokovic and Dr. Tian Zhang for their constructive feedback in our group meetings. iv Contents Abstract iii Acknowledgements iv Declaration of Academic Achievement xvii 1 Introduction2 1.1 Processors.................................2 1.1.1 Uniprocessors...........................2 1.1.2 Multicore Processors.......................6 1.1.3 Microprocessor Performance and Trends............7 1.2 Object-Oriented Programming Languages...............7 1.2.1 Sequential Programming.....................8 1.2.2 Concurrent Programming....................9 1.3 Problems This Thesis Addresses..................... 10 1.4 Contributions............................... 11 1.5 Structure of the Thesis.......................... 11 2 Concurrency Models 12 2.1 Shared Variables............................. 13 v 2.1.1 Synchronization.......................... 13 2.1.2 Semaphores............................ 15 2.1.3 Conditional Critical Regions................... 17 2.1.4 Monitors.............................. 18 2.1.5 Futures.............................. 20 2.1.6 Action Systems.......................... 21 2.2 Message Passing.............................. 29 2.2.1 Asynchronous Message Passing................. 29 2.2.2 Synchronous Message Passing.................. 30 2.2.3 Implementations......................... 31 3 Lime 33 3.1 What is Lime............................... 33 3.2 Why Lime................................. 33 3.2.1 Actions.............................. 34 3.2.2 Methods.............................. 35 3.2.3 Method Calls........................... 36 3.3 Lime Syntax................................ 36 3.4 Lime Semantics.............................. 39 3.4.1 Core Language.......................... 39 3.4.2 Concurrent Objects........................ 43 3.5 Lime Examples.............................. 46 3.5.1 Semaphores............................ 46 3.5.2 Dining Philosophers....................... 46 3.5.3 Reader-Writer........................... 49 3.5.4 Delayed Doubler......................... 51 vi 3.5.5 Priority Queue.......................... 52 3.5.6 Leaf-oriented Trees........................ 54 4 Contributions to Lime 57 4.1 Previous Implementations of Lime.................... 57 4.1.1 Implementation of Lime Using Monitors............ 57 4.1.2 Implementation of Lime Using Condition Variables...... 58 4.2 The Addressed Problems......................... 58 4.2.1 Threads.............................. 58 4.2.2 Stack Mechanisms........................ 58 4.2.3 Guard Implementations..................... 59 4.3 Contributions of This Work....................... 59 4.3.1 Lime Compiler.......................... 59 4.3.2 Lime Runtime System...................... 60 5 Stack Mechanisms 63 5.1 Introduction................................ 63 5.2 Related Work............................... 64 5.2.1 Single-Threaded Call Stack................... 64 5.2.2 Shared Call Stacks........................ 66 5.2.3 Cactus Stacks........................... 66 5.2.4 Stack Mechanisms Summary................... 67 5.3 Experimental Setup............................ 68 5.4 Moore-Oliva's Lime Calling Convention................. 69 5.5 Implemented Stack Mechanisms..................... 70 5.5.1 Traditional Fixed-Size Stack with \Caller-cleanup"...... 70 5.5.2 Traditional Fixed-Size Stack with \Callee-cleanup"...... 71 vii 5.5.3 Per Procedure \Heap" Allocation................ 72 5.5.4 LookAhead Stack Mechanism.................. 72 5.5.5 Guard-Page Stack Mechanism.................. 73 5.6 Experiments................................ 75 5.6.1 Results............................... 77 5.6.2 Impact of Processor Architecture................ 78 5.6.3 Impact of Usage Profile in Single-Threaded Runs....... 78 5.6.4 Impact of Usage Profile in Multi-Threaded Runs........ 82 6 Guarded Commands in Lime 88 6.1 Lightweight Thread Implementations.................. 88 6.1.1 Erlang Process.......................... 88 6.1.2 Goroutine............................. 89 6.2 Previous Implementations of Guarded Commands in Lime...... 91 6.2.1 Busy Waiting........................... 92 6.2.2 Previous Implementations.................... 92 6.3 Guarded Commands Implementations.................. 93 6.3.1 Translation Schemes....................... 94 6.3.2 Context Switches......................... 96 6.3.3 Lime Runtime System...................... 97 6.4 Experiments................................ 102 6.4.1 Priority Queue.......................... 103 6.4.2 MapReduce............................ 105 6.4.3 Leaf-Oriented Tree........................ 107 6.4.4 The Santa Claus Problem.................... 110 6.4.5 The Chameneos Game...................... 113 viii 6.4.6 Summary............................. 116 7 Conclusions 118 A Priority Queue Examples 129 A.1 Erlang................................... 129 A.2 Go..................................... 130 A.3 Haskell................................... 132 A.4 Java.................................... 134 A.5 Pthread.................................. 137 B Leaf-oriented Tree Examples 142 B.1 Erlang................................... 142 B.2 Go..................................... 144 B.3 Haskell................................... 147 B.4 Java.................................... 149 B.5