Performance Monitoring of Ruby Applications
Total Page:16
File Type:pdf, Size:1020Kb
JOHANNES KEPLER UNIVERSITAT¨ LINZ JKU Faculty of Engineering and Natural Sciences Performance Monitoring of Ruby Applications Master’s Thesis submitted in partial fulfillment of the requirements for the academic degree Diplom-Ingenieur in the Master’s Program Computer Science Submitted by: Martin Ennemoser At the: Institut f¨urSystemsoftware Advisor: o.Univ.-Prof. Dipl.-Ing. Dr.Dr.h.c. Hanspeter M¨ossenb¨ock Linz, May 2015 Abstract Ruby is a modern scripting language which has gained great popularity, espe- cially among web developers, in the last couple of years. Monitoring the performance of Ruby web applications is vital because website administrators need to know how well their websites are performing, especi- ally when they are under high load. Existing Ruby performance monitoring tools are either slow, not flexible enough or don’t gather enough information about the application under diagnosis in order to find potential bottlenecks. This thesis presents a novel approach which is able to collect performance- related information from Ruby applications at run time. The presented ap- proach allows the instrumentation of arbitrary Ruby methods without the need of application code changes. This approach is based on metaprogram- ming methods which are provided by Ruby. The implemented prototype, which was developed during this thesis, is in- tegrated into dynaTrace, an application performance management (APM) solution for distributed applications. The evaluation of this prototype shows that the presented approach is a feasible way to gather performance informa- tion about Ruby applications. For that matter, this approach not just works for Ruby web applications but for arbitrary Ruby applications. i Kurzfassung Ruby ist eine moderne Skriptsprache, welche große Popularität, besonders unter Webentwicklern in den letzten Jahren erreicht hat. Das Überwachen der Performance von Ruby Webapplikationen ist für Website-Administratoren unerlässlich, vor allem wenn diese Applikationen unter hoher Last stehen. Existierende Diagnose-Tools erzeugen entweder einen zu hohen Overhead, sind nicht flexibel genug oder sammeln nicht genug Informationen über die überwachten Ruby Applikationen, um bestehende Performance-Engpässe zu entdecken. Diese Masterarbeit präsentiert einen neuartigen Ansatz, welcher in der Lage ist, Performance-Daten von Ruby Applikationen zur Laufzeit zu sammeln. Der präsentierte Ansatz erlaubt die Instrumentierung von beliebigen Ruby Methoden, ohne dass der Applikations-Code geändert werden muss. Dieser Ansatz basiert auf Metaprogrammierungs-Methoden, welche Ruby zur Ver- fügung stellt. Der implementierte Prototyp, welcher während dieser Arbeit entwickelt wur- de, ist in dynaTrace, eine Application Performance Management (APM) Lö- sung für verteilte Anwendungen integriert. Die Evaluierung dieses Prototypen zeigt, dass der präsentierte Ansatz ein brauchbarer Weg ist, um Performance- Daten von Ruby Applikationen zu sammeln. Dabei ist dieser nicht nur für Ruby Webapplikationen, sondern für beliebige Ruby Applikationen einsetz- bar. ii Contents Contents iii 1 Introduction 1 1.1 Motivation . .1 1.2 Objective . .2 1.3 Requirements . .3 2 dynaTrace Diagnostics 5 3 The Ruby Environment 7 3.1 The Ruby Programming Language . .7 3.2 Ruby Gems . .7 3.3 Interpreters . .9 3.3.1 MRI . .9 3.3.2 Rubinius . .9 3.3.3 JRuby . 10 3.4 Ruby on Rails . 10 4 Application Inspection 13 4.1 Overview . 13 4.2 Entry List . 14 4.3 Static Inspection . 16 4.4 Dynamic Inspection . 17 iii CONTENTS iv 5 Dynamic Inspection Approaches 20 5.1 Overview . 20 5.2 set_trace_func . 21 5.2.1 Dynamic Inspection Approach . 22 5.2.2 Advantages . 24 5.2.3 Disadvantages . 25 5.3 Active Support Notification . 25 5.3.1 Dynamic Inspection Approach . 26 5.3.2 Advantages . 27 5.3.3 Disadvantages . 27 5.4 method_added/singleton_method_added . 27 5.4.1 Dynamic Inspection Approach . 28 5.4.2 Advantages . 29 5.4.3 Disadvantages . 30 5.5 The require Method . 30 5.5.1 Dynamic Inspection Approach . 31 5.5.2 Advantages . 32 5.5.3 Disadvantages . 32 5.6 Chosen Dynamic Inspection Approach . 32 6 Instrumentation 34 6.1 Overview . 34 6.2 Static/Dynamic Instrumentation . 36 6.3 Ruby Code Injection . 37 6.4 Method Aliasing . 38 6.5 Defining New Methods . 38 6.6 Placement of the Instrumentation Code . 41 7 Native Agent Integration Approaches 43 7.1 MRI Extensions . 43 7.1.1 Advantages . 45 7.1.2 Disadvantages . 46 CONTENTS v 7.2 Ruby FFI . 46 7.2.1 Advantages . 47 7.2.2 Disadvantages . 47 7.3 JRuby Extensions . 47 7.3.1 Advantages . 50 7.3.2 Disadvantages . 51 7.4 Conclusion . 51 8 Architecture and Implementation 52 8.1 Agent Architecture . 52 8.2 Component Overview . 52 8.3 Instrumentation Engine . 54 8.3.1 Static Inspection Algorithm . 54 8.3.2 Dynamic Inspection Algorithm . 57 8.4 Agent Extension Interface . 59 8.5 Native Interface . 60 8.6 Agent Injection . 61 8.6.1 Agent Injection with Gemfile . 61 8.6.2 Agent Injection without Gemfile . 62 9 Sensors 63 9.1 Method Sensor . 63 9.1.1 Implementation . 64 9.1.2 Functionality . 64 9.2 Middleware Sensor . 65 9.2.1 Rack . 66 9.2.2 Implementation . 67 9.3 Other Sensors . 69 9.3.1 HTTP Sensor . 69 9.3.2 Active Record Sensor . 70 9.3.3 Rails ActionView/ActionController Sensors . 70 CONTENTS vi 10 Related Work 73 10.1 ruby-prof . 73 10.1.1 Advantages . 74 10.1.2 Disadvantages . 75 10.2 Bullet . 75 10.2.1 Advantages . 75 10.2.2 Disadvantages . 76 10.3 Railsbench . 76 10.3.1 Advantages . 77 10.3.2 Disadvantages . 77 10.4 New Relic APM . 77 10.4.1 Advantages . 79 10.4.2 Disadvantages . 79 11 Case Study 80 11.1 Shoppe . 80 11.2 Agent Deployment . 80 11.3 PurePath Samples . 82 11.4 Method Instrumentation Overhead . 82 11.4.1 Run Time Overhead . 83 11.4.2 Memory Overhead . 83 11.5 Performance Evaluation of Shoppe . 83 11.5.1 Load Time . 83 11.5.2 Average HTTP Request Time . 84 11.5.3 CPU Consumption . 84 11.5.4 Memory Consumption . 84 12 Future Work 91 13 Conclusion 92 List of Figures 95 Listing 97 Chapter 1 Introduction This chapter points out the relevance of this thesis and describes the objec- tives and requirements that had to be fulfilled. 1.1 Motivation Nowadays, many websites are built using scripting languages along with web application frameworks in order to simplify the development of dynamic web- sites, web applications or web services. Many different scripting languages and frameworks exist which have strengths and weaknesses and are used for specific kinds of tasks. One famous scripting language is Ruby, which is actually a general programming language but is mostly used for the develop- ment of web applications. Ruby has become popular with the emergence of Ruby on Rails [1] (Rails), which is a web application framework written in Ruby. Rails has gained great popularity among web developers during the last years. According to builtWith [2], Ruby on Rails is listed as one of the most popular frameworks currently. Website owners are interested in how well their Ruby-based websites per- form and whether there are any performance bottlenecks. There are already tools available for monitoring and analyzing the performance of Ruby web applications. But these tools are either slow, framework specific or just give superficial performance or error information. 1 CHAPTER 1. INTRODUCTION 2 1.2 Objective The objective of this thesis was the development of a tool (a so called Agent)1 which is able to collect performance-related information from Ruby applica- tions. This tool has to perform the following tasks: • Interception of HTTP requests which are made to the application. • Instrumentation of the application under diagnosis in order to collect performance-related information like response times, execution times or throughput. Furthermore, it should also be possible to collect method- related information like parameters or return values. • Sending the collected data to a central server for evaluation and to track execution. This tool should not only be usable for web applications but for general Ruby applications. However, it has to be noted that Ruby is mainly used in the field of web development. To achieve the objectives mentioned above the following steps had to be taken: 1. Research of the most important Ruby interpreters: Which interpreters are currently used? Which of them are relevant for this thesis? 2. Research of the most important Ruby web application frameworks: Which web application frameworks are important beside Ruby on Rails? 3. Research of Ruby performance tools: Which performance tools are al- ready available? How do they work? How can they be used in terms of this thesis? 4. Research of injection: Which possibilities exist in order to inject the agent into the application at run time? 5. Implementation of the Agent: To implement a prototype, the following questions have to answered first: (a) Is it necessary to access the internals of the interpreter in order to obtain performance metrics? If yes, how could this be done? 1The terms dynaTrace Ruby Agent, Ruby Agent and Agent will be used synonymously. CHAPTER 1. INTRODUCTION 3 (b) Is it possible to get performance metrics directly from the frame- works? (c) How could the dynaTrace Native Agent be integrated into the Ruby process? 6. Implementation of the Sensors: How could custom code be injected into the application? How could the injection overhead be kept small? How could performance information be collected and how are they transmit- ted to the agent? 7. Evaluation of the prototype: Test the Agent on a real world application to assess its performance. 1.3 Requirements The Agent has to fulfill the following requirements: • Run inconspicuously: The Agent runs in the background of the Ruby process. However, it must not alter the program behavior or even worse, crash the program.