Optimizing Runtime Performance of Dynamically Typed Code
Total Page:16
File Type:pdf, Size:1020Kb
Optimizing Runtime Performance of Dynamically Typed Code Jose Quiroga Alvarez PhD Supervisor Dr. Francisco Ortin Soler Department of Computer Science University of Oviedo A thesis submitted for the degree of Doctor of Philosophy Oviedo, Spain June 2016 Acknowledgements This work has been partially funded by the Spanish Department of Science and Technology, under the National Program for Research, Development and Innovation. The main project was Obtaining Adapt- able, Robust and Efficient Software by including Structural Reflection to Statically Typed Programming Languages (TIN2011-25978). The work is also part of the project entitled Improving Performance and Robustness of Dynamic Languages to develop Efficient, Scalable and Reliable Software (TIN2008-00276). I was awarded a FPI grant by the Spanish Department of Science and Technology. The objective of these grants is to support gradu- ate students wishing to pursue a PhD degree associated to a specific research project. This PhD dissertation is associated to the project TIN2011-25978 (previous paragraph). This work has also been funded by Microsoft Research, under the project entitled Extending dynamic features of the SSCLI, awarded in the Phoenix and SSCLI, Compilation and Managed Execution Request for Proposals. Part of the research discussed in this dissertation has also been funded by the European Union, through the European Regional Development Funds (ERDF); and the Principality of Asturias, through its Science, Innovation Plan (grant GRUPIN14-100). Abstract Dynamic languages are widely used for different kinds of applications including rapid prototyping, Web development and programs that require a high level of runtime adaptiveness. However, the lack of compile-time type information involves fewer opportunities for com- piler optimizations, and no detection of type errors at compile time. In order to provide the benefits of static and dynamic typing, hybrid typing languages provide both typing approaches in the very same programming language. Nevertheless, dynamically typed code in this languages still shows lower performance and lacks early type error detection. The main objective of this PhD dissertation is to optimize runtime performance of dynamically typed code. For this purpose, we have defined three optimizations applicable to both dynamic and hybrid typing languages. The proposed optimizations have been included in an existing compiler to measure the runtime performance benefits. The first optimization is performed at runtime. It is based on the idea that the dynamic type of a reference barely changes at runtime. Therefore, if the dynamic type is cached, we can generate specialized code for that precise type. When there is a cache hit, the program will perform close to its statically typed version. For this purpose, we have used the DLR of the .Net framework to optimize all the existing hybrid typing languages for that platform. The optimizations are provided as a binary optimization tool, and included in an existing compiler. Performance benefits range from 44.6% to 11 factors. The second optimization is aimed at improving the performance of dynamic variables holding different types in the same scope. We have defined a modification of the classical SSA transformations to improve the task of type inference. Due to the proposed algorithms, we infer one single type for each local variable. This makes the generated code to be significantly faster, since type casts are avoided. When a refer- ence has a flow sensitive type, we use union types and nested runtime type inspections. Since we avoid the use of reflection, execution time is significantly faster than existing approaches. Average performance improvements range from 6.4 to 21.7 factors. Besides, the optimized code consumes fewer memory resources. The third optimization is focused on the improvement of multiple dispatch for object-oriented languages. One typical way of providing multiple dispatch is resolving method overload at runtime: depend- ing on the dynamic types of the arguments, the appropriate method implementation is selected. We propose a multiple dispatch mech- anism based on the type information of the arguments gathered by the compiler. With this information, a particular specialization of the method is generated, making the code to run significantly faster than reflection or nested type inspection. This approach has other benefits such as better maintainability and readability, lower code size, pa- rameter generalization, early type error detection and fewer memory resources. Keywords Dynamic typing, runtime performance, optimization, hy- brid dynamic and static typing, Dynamic Language Run- time, Static Single Assignment, SSA Form, multiple dis- patch, multi-method, union types, reflection, StaDyn, .Net Contents Contents iv List of Figures vi 1 Introduction1 1.1 Motivation . .1 1.2 Contributions . .3 1.3 Structure of the document . .4 2 Related Work5 2.1 The StaDyn programming language . .5 2.1.1 Type inference . .6 2.1.2 Duck typing . .6 2.1.3 Dynamic and static typing . .8 2.1.4 Implicitly typed parameters . .9 2.1.5 Implicitly typed attributes . 10 2.1.6 Alias analysis for concrete type evolution . 11 2.1.7 Implementation . 11 2.2 Hybrid static and dynamic typing languages . 12 2.3 Optimizations of dynamically typed virtual machines . 15 2.4 Optimizations based on the SSA form . 16 2.5 Multiple dispatch (multi-methods) . 17 3 Optimizing Dynamically Typed Operations with a Type Cache 20 3.1 The Dynamic Language Runtime . 21 3.2 Optimization of .Net hybrid typing languages . 23 3.2.1 VB optimizations . 25 3.2.2 Boo optimizations . 30 3.2.3 Cobra optimizations . 30 3.2.4 Fantom optimizations . 30 3.2.5 StaDyn optimizations . 34 3.3 Implementation . 35 3.3.1 Binary program transformation . 35 3.3.2 Compiler optimization phase . 35 3.4 Evaluation . 36 3.4.1 Methodology . 36 3.4.1.1 Selected languages . 36 3.4.1.2 Selected benchmarks . 37 iv Contents 3.4.1.3 Data analysis . 38 3.4.1.4 Data measurement . 39 3.4.2 Start-up performance . 40 3.4.2.1 Discussion . 41 3.4.3 Steady-State performance . 42 3.4.3.1 Discussion . 43 3.4.4 Memory consumption . 44 3.4.4.1 Discussion . 44 4 Optimizations based on the SSA form 46 4.1 SSA form . 48 4.2 SSA form to allow multiple types in the same scope . 49 4.2.1 Basic blocks . 50 4.2.2 Conditionals statements . 52 4.2.3 Loop statements . 53 4.2.4 Union types . 55 4.2.5 Implementation . 57 4.3 Evaluation . 57 4.3.1 Methodology . 57 4.3.2 Start-up performance . 58 4.3.3 Steady-state performance . 59 4.3.4 Memory consumption . 61 4.3.5 Compilation time . 62 5 Optimizing Multimethods with Static Type Inference 63 5.1 Existing approaches . 64 5.1.1 The Visitor design pattern . 64 5.1.2 Runtime type inspection . 66 5.1.3 Reflection . 67 5.1.4 Hybrid typing . 68 5.2 Static type checking of dynamically typed code . 69 5.2.1 Method specialization . 70 5.3 Evaluation . 72 5.3.1 Methodology . 72 5.3.2 Runtime performance . 73 5.3.3 Memory consumption . 78 6 Conclusions 80 6.1 Future Work . 81 A Evaluation data of the DLR optimizations 82 B Evaluation data of the SSA optimizations 86 C Evaluation data for the multiple dispatch optimizations 90 D Publications 96 References 98 v List of Figures 1.1 Hybrid static and dynamic typing example in C#. .2 2.1 Type inference of var and dynamic references. .6 2.2 Static duck typing. .7 2.3 Static var reference. .8 2.4 Implicitly typed parameters. .9 2.5 Implicitly typed attributes. 10 2.6 Alias analysis. 11 3.1 Example VB program with (right-hand side) and without (left- hand side) DLR optimizations. 22 3.2 Architecture of the two optimization approaches. 23 3.3 Transformation of common expressions. 26 3.4 Transformation of common type conversions. 27 3.5 Transformation of indexing operations. 28 3.6 Transformation of method invocation and field access. 29 3.7 Optimization of Boo basic expressions and type conversions. 31 3.8 Optimization of Boo invocations, indexing and member access. 32 3.9 Cobra optimization rules. 33 3.10 Fantom optimization rules. 34 3.11 StaDyn optimization rules. 34 3.12 Class diagram of the binary program transformation tool. 36 3.13 Start-up performance improvement for Pybench. 41 3.14 Start-up performance improvement. 42 3.15 Steady-state performance improvement. 42 3.16 Memory consumption increase. 44 4.1 The dynamically typed reference number holds different types in the same scope. 46 4.2 Type conversions must be added when number is declared as object. 47 4.3 A SSA transformation of the code in Figure 4.1........... 47 4.4 CFG for the code in Figure 4.5 (left) and its SSA form (right). 48 4.5 An iterative Fibonacci function using dynamically typed variables. 49 4.6 SSA transformation of a sequence of statements. 51 4.7 SSA transformation of statements. 51 4.8 SSA transformation of expressions. 51 4.9 Original CFG of an if-else statement (left), and intermediate SSA representation (middle), and its final SSA form (right). 52 vi List of Figures 4.10 SSA transformation of if-else statements. 53 4.11 Original CFG of a while statement (left), and intermediate SSA representation (middle) and its final SSA form (right). 54 4.12 SSA transformation of while statements. 55 4.13 A simplification of the StaDyn compiler architecture [1]. 55 4.14 Type inference of the SSA form. 56 4.15 Start-up performance of Pybench, relative to StaDyn without SSA. 59 4.16 Start-up performance of all the benchmarks, relative to StaDyn without SSA. 60 4.17 Steady-state performance of all the benchmarks, relative to C#.