RubyRunCE

 

Version 0.9.7

 

Installation and User Guide

 


 

1      Table of Contents

1        Table of Contents. 2

2        Introduction to RubyRunCE. 3

3        Version 0.9.7 Features. 4

4        Known Constraints of RubyRunCE V0.9.7. 5

5        Installation. 6

5.1        Software pre-requisite (Windows platform only) 6

5.1.1        Selecting the Gem.. 6

5.1.2        Installing the Gem.. 6

5.1.3        Verifying the installation. 7

5.1.4        Configuring. 7

6        Usage Scenarios. 9

6.1        Getting Started. 9

6.2        Understanding Code Path. 9

6.3        Controlling Instrumentation Scope. 10

6.4        Understanding Response Time Components. 11

6.5        Configuring for a High-Traffic Environment 12

6.6        Handling Hung Servers or Requests. 12

6.7        Terminating Hung Threads. 13

6.8        Quick Checks for Potential Memory Leaks. 14

7        Performance Summary Reports (RSS feed) 16

7.1        Average throughput per minute. 16

7.2        Top 10 slowest Rails requests. 16

7.3        Average Rails request response time by action by controller with breakdown. 17

8        Method Level Trace. 18

9        Dynamic Application Discovery (DAD) 20

10     Transaction Log. 22

11     Appendices. 23

11.1          Technical Concepts. 23

11.1.1     Hooks. 23

11.1.2     Instrumentation. 23

11.1.3     Logging. 23

11.1.4     Tracing. 23

11.1.5     Monitoring. 24

11.2          RubyRun Options file (rubyrun_opts.yml) 24

11.2.1     RubyRun options file. 24

11.2.2     Properties. 24

11.3          Diagnostic Commands. 28

11.3.1     Local commands. 28

11.3.2     Global commands. 29

11.4          Configuring RSS Readers. 29

11.5          Lab Tested Platforms and Servers. 31

11.6          Performance. 32

 

2       Introduction to RubyRunCE

 

  • RubyRun Community Edition (RubyRunCE, also referred to as RubyRun in the rest of this document) is an application performance diagnostic solution for Ruby developers. It is meant to help them gain visibility into the behavior of their code in different operating environments, and understand the response time hotspots of typical Rails requests.

 

  • Developers can also use RubyRun to diagnose typical application performance problems such as hung and slow transactions in development, QA, stress test, and production environments.

 

  • RubyRun uses meta-programming techniques to selectively instrument Ruby methods to capture critical timing and diagnostic data at the method level. Unlike the Ruby Profiler or Benchmark module RubyRun operates at the request (http), class, and method level but not at the statement level. This allows developers to identify performance problems that occur under load without obscuring the root cause by greatly changing the application’s performance characteristics.

 

  • RubyRun is installed via the standard gem process and operates at the Ruby level. It does not use Rails, Webrick, or Mongrel callbacks. Once RubyRun is installed, it can be activated and de-activated via a simple Ruby interpreter command-line switch.

 

  • RubyRun supports both pure Ruby as well as Ruby-on-Rails applications. For Ruby-on-Rails applications, RubyRun supports both the Mongrel and Webrick application servers.

 

  • RubyRun is intended to be an out-of-the-box experience with minimal installation effort. Most importantly, it does not require any change in the environment or code to run RubyRun with most typical Ruby or Ruby-on-Rails applications.

 

  • Minimum performance overhead when instrumented optimally and run without tracing.

3      Version 0.9.7 Features

 

  • Easy engaged/disengaged design using the Ruby –r option.

 

  • Supports a set of functions that facilitate quick problem determination, application diagnosis, performance analysis and reporting:

 

Ø  Method trace by Rails request or Ruby script, with the option to debug arguments and/or calling object

 

Ø  Rails request response time summary and breakdown by Controller/Action

 

Ø  Individual Rails request log with response time breakdown

 

Ø  Top 10 slowest Rails request by Controller/Action

Ø  Request Throughput per minute chart

 

Ø  Thread kill with stack trace

 

Ø  Thread status and top stack frame of Ruby threads

 

Ø  Object map of a Ruby process

 

  • Instrumentation toolkit - allows developers to control its tracing scope by including additional or excluding existing application classes/methods via simple customization:

 

Ø  Automatically identify methods for instrumentation given a set of application paths

 

Ø  Selectively and explicitly instrument designated set of methods

 

Ø  Selectively and explicitly exclude designated set of methods from being instrumented

 

  • Dynamic Application Discovery - automatically instruments dynamically added classes, objects and methods as they are added into the Ruby process on the fly.

 

  • For certain types of reports, results can be published in RSS and/or HTML graph format, allowing quick and easy access to performance reports without additional infrastructure.

 

  • CSV format is supported for certain types of reports, allowing results to be imported into a variety of tools.

4      Known Constraints of RubyRunCE V0.9.7

 

  • This release requires write access to the site_ruby directory to simplify the startup command string for RubyRun.

 

  • Methods using the super keyword will not be instrumented, and if instrumented for whatever reason, may or may not work.  They should be removed from the instrumentation scope if they cause exceptions.

 

Ø  Basically RubyRun automatically excludes all methods found in the APP_PATHS from instrumentation if they use the keyword super. However, if additional classes or methods are added into the INCLUDE_HASH, it is the responsibility of the user to ensure that these methods are ‘super’ free. They should be excluded (by removing them from the INCLUDE_HASH or putting them in the EXCLUDE_HASH) if an exception does occur during runtime.

 

  • RubyRun is designed to be an application performance diagnostic tool. Non-application libraries such as Ruby, Rails, Mongrel, or other vendors’ libraries should not be subjected to instrumentation in a production environment unless they have been tested.

 

  • The scope of performance reports is at the process level. Performance reports at the cluster level are not supported in this release of RubyRun.

 

  • cmd_soft_kill and cmd_hard_kill work differently in Webrick than they do in Mongrel. Webrick attempts to rescue thread exceptions and the stack trace is captured in its own log (development.log, production.log etc.). In the case of cmd_hard_kill, the Webrick main thread ignores the signal, refuses to terminate, and continues its business as normal.

 

  • JRuby should be supported but lab tests have not been performed.

5      Installation

5.1    Software pre-requisite (Windows platform only)

 

RubyRun requires the following library if it runs on Windows:

 

Microsoft Visual C++ 2008 Redistributable Package (x86). The download is available at http://www.microsoft.com/downloads/details.aspx?FamilyID=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&displaylang=en

 

5.1.1    Selecting the Gem

 

RubyRun is packaged in standard Ruby gem format. There are two gems available. One is platform dependent gem (rubyrun-0.9.7.gem) which supports Windows, Linux and Mac OS X platform. The other one is a platform independent gem (rubyrun-0.9.7-universal.gem), which contains the native source code for automatic compilation during gem installation process.

 

Download rubyrun-0.9.7.gem if you are using one of the following platforms:

 

·         Windows x86 32 bit

·         Linux x86 32 bit

·         Mac OS X v10.4 PPC 32-bit

·         Mac OS X v10.5 x86 32-bit

 

Note: You can still use rubyrun-0.9.7.gem to install RubyRun even if you are using an unsupported platform/hardware. In that case, the installation will finish without installing the native library and stack trace will not be available in cmd_status, cmd_soft_kill and cmd_hard_kill.

 

If you need the stack trace function and your operating system and hardware combination is not in the above mentioned list, you can download rubyrun-0.9.7-universal.gem. It contains the native source code for automatic compilation during the gem installation process, provided that the GCC compiler tools and appropriate runtime threading libraries is available in the target machine.

 

To use rubyrun-0.9.7-universal.gem to compile the native library, the following prerequisites are required:

 

·         Appropriate compilers (GCC etc.)

·         Appropriate runtime libraries

5.1.2    Installing the Gem

 

To use rubyrun-0.9.7.gem and install RubyRun, use the following gem command:

 

gem install rubyrun

 

Note: This command will download rubyrun-0.9.7.gem from RubyForge.

 

To use rubyrun-0.9.7-universal.gem and install RubyRun, download the file from http://www.rubysophic.com/download, save it in a directory and use gem command to install it:

     

      gem install rubyrun-0.9.7-universal.gem

 

5.1.3    Verifying the installation

 

A successful installation will create the following subdirectories and files:

 

·         Obtain the gem directory path via this command:

gem environment gemdir

 

·         The following directory should have been created:

<gem dir>/gems/rubyrun-0.9.7

 

·         The following files must be present inside the folder

<gem dir>/gems/rubyrun-0.9.7/lib/rubyrun

 

a.       rubyrun.rb              

b.      rubyrun_boot__.rb

c.       rubyrun_buffer_mgr__.rb 

d.      rubyrun_commander__.rb

e.       rubyrun_dad__.rb         

f.       rubyrun_globals.rb      

g.      rubyrun_html__.rb       

h.      rubyrun_html_writer__.rb  

i.        rubyrun_initializer__.rb  

j.        rubyrun_instrumentor__.rb 

k.      rubyrun_monitor__.rb      

l.        rubyrun_report__.rb

m.    rubyrun_rss__.rb

n.      rubyrun_tracer__.rb

o.      rubyrun_utils__.rb

p.      rubyrunnative__.*

 

* The presence of a native library. Its file extension is dependent on the platform that RubyRun is installed. Stack trace function is not available if the library is not present.

5.1.4    Configuring

 

  • There is NO need for configuration in this release of RubyRun.

 

  • RubyRun will automatically create a working directory called “rubyrun” in the current directory of the Ruby process the first time when it is started. It also creates a copy of the properties file under this directory for further customization, defaulting some of the properties which you might need to change afterwards followed by a restart.

 

  • RubyRun will create further subdirectories under the “rubyrun” subdirectory. For example:

 

Ø  log                   à (Directory where the log files are stored)

Ø  report               à (Directory where the reports are stored)

Ø  signatures        à(Directory where the signature files are stored)

 

Inside the log and report subdirectories file names will have a process id as part of the name to distinguish multiple processes within an OS image.


 

6      Usage Scenarios

6.1    Getting Started

 

To get started with RubyRun, simply start the Ruby application using one of the following:

 

Ø  Ruby Applications

 

ruby –rubyrun   <other options>

 

Ø  Rails Applications

 

ruby –rubyrun  script/server

 

         Note that the –r switch is essential. In this case, the –r switch instructs the Ruby interpreter to load the early code called rubyrun.rb from the site_ruby directory.

 

You should check out the outputs in the self-explanatory subdirectories under the “rubyrun” subdirectory in the directory where your start your application.. All filenames end with the process id of your Rails server or Ruby script. Now you should also verify the values of APP_PATHS and DB_ADAPTER_HASH properties in rubyrun_opts.yml. Both properties have been automatically set by RubyRun but can be customized. Customization is to be performed on this copy of rubyrun_opts.yml by changing the values of the properties.

 

In a Rails environment, start by pointing APP_PATHS to where the controller classes are (i.e. app/controllers) if it hasn’t been correctly set so, or in the case of a Ruby script, the directory where your application ruby files reside. APP_PATHS only takes absolute paths.

 

For example, if you are using the application Redmine, set its value to the following if it has not been set correctly:

 

APP_PATHS: ['/redmine-0.7.1/app/controllers']

 

Second, customize the DB_ADAPTER_HASH property depending on the type of database server used by the application. RubyRun defaults that to MySQL.

 

For example, if you are using SQLite2 database server, set:

 

DB_ADAPTER_HASH: {ActiveRecord::ConnectionAdapters::SQLite2Adapter: [execute]}

 

Save your changes. Restart your Ruby application.

6.2    Understanding Code Path

 

It is very easy to use RubyRun to produce a trace of all the key methods in a chronological sequence for a Rails request, or simply a batch Ruby script.

 

Customize the TRACH_HASH property in rubyrun_opts.yml as follows:

 

TRACE_HASH = {*: []}

 

This instructs RubyRun to produce entry/exit trace entries for every method that has been instrumented.

 

RubyRun traces a Rails request (a real http request that is served by the MVC mechanism of the Rails engine, not a static page or a request satisfied through the Rails cache mechanism). By default, RubyRun also captures all SQL statements issued by ActiveRecord through the database adapter, assuming you have set the correct value in the property DB_ADAPTER_HASH. The trace output is a html file in the report subdirectory under the “rubyrun” subdirectory.

 

Developers can use the trace output to verify code path, inspect SQL statements, and spot logic anomalies. Individual method response times can be easily identified in a trace, helping developers rapidly isolate performance problems.

6.3    Controlling Instrumentation Scope

 

There are times when you may want to get a full trace of all your application code because you want to find the culprit of a known delay. At other times, however, you may determine that certain Ruby classes are generating large numbers of “noise” trace entries.

 

In either case, instrumentation scope can be refined by using the properties APP_PATHS, INCLUDE_HASH and EXCLUDE_HASH in rubyrun_opts.yml. If you want to see more application methods in a trace, simply add more directories into the APP_PATHS if the application is not contiguously located within one directory tree. Hashes are keyed on class name with an array of method names, allowing you to specify which class(es) or method(s) will be instrumented. For more information, refer to rubyrun_opts.yml in the Appendices.

 

For example, in a trace report, you see a large number of method entry and exit traces from the ActiveRecord model Order, as well as the validate_account method from the Ruby class Account. These can be eliminated by including the following line in the options file:

 

            EXCLUDE_HASH: {Order: [], Account: [validate_account]}

 

On the other hand, instrumentation scope can be extended by using the INCLUDE_HASH option. For example, by including the following line in the options file method trace will include all the methods of objects PaymentGateway and PaymentManager which are not to be found within the APP_PATHS scope:

 

            INCLUDE_HASH: {PaymentGateway: [], PaymentManager: []}

 

In a nutshell, APP_PATHS allows you to specify which directories RubyRun will expand and scan the Ruby classes/methods for class and module names. The classes in these directories will be instrumented automatically when they are loaded. INCLUDE_HASH and EXCLUDE_HASH are additional finer-grained parameters which allow you to specify the instrumentation (or de-instrumentation) scope at the class and method level. By making use of these options judiciously, you can achieve a balance between detailed data and application performance.

6.4    Understanding Response Time Components

 

RubyRun measures the response time of a Rails request with a breakdown of the components that usually account for most of the time spent. As there is no standard form or mechanism for determining performance, response time reporting is not supported for pure Ruby scripts.

 

Request timings are collected, summarized, and broken down into 6 components according to the RubyRun model of response time decomposition:

 

a.       Total Response Time

 

The entire time the request spent in the dispatcher of an application server, during which Rails can not serve any other dynamic, non-static request. This is total time that the request has spent within an application server.

 

b.      Action Time

 

From the start of the controller/action method till it ends. Action time is a subset of the total response time. Action Time DOES NOT include Filter and Verification processing of a controller.

 

c.       Database I/O Time

 

Total time spent in the database adapter execute method, which DOES not include Rails MODEL processing time. The database adapter handles all physical interactions with the database server, which in turn is likely to be responsible for most of the ActiveRecord delay of a typical database-centric Rails request.

 

Database I/O time can be part of Action time and View time depending on how the application is written.

 

d.      View Time

 

Total time spent in view rendering, including the layout. View time can include time spent in database adapters depending if there are database manipulations during the view processing phase. View time can also be part of the Action Time depending on how the application is written.

 

e.       Dispatch Delay Time

 

After being scheduled by the dispatcher and before the execution of the controller/action method, Rails can put the request on a mutex wait if Rails is indeed running in a non-concurrent mode (except if the request is a static one which RubyRun will not monitor). Dispatch delay tells you how much time a request spent waiting due to a busy server. If the delay is frequent and long, it is a good indicator that more application servers may be required.

 

f.       Un-captured Time

 

Un-captured time represents the portions of the response time that do not fall into one of the above categories. Un-captured time is part of the Total Response Time and includes the following elements:

 

         Rails Filters and Verification

         Mongrel or Webrick or Rails overhead (for example, scheduling, dispatching, and other processing)

         Time spent on any other non-instrumented application methods before the invocation of a controller/action method and also after its termination.

6.5    Configuring for a High-Traffic Environment

 

For a Rails application running in a load-test, staging, or production environment, the following settings are recommended:

 

# Turn trace off

TRACE_HASH = {}

 

# Limit instrumentation scope to controller level

APP_PATHS: ['/redmine-0.7.1/app/controllers']

 

# Show added methods

DAD: true

 

# Cut report every hour

REPORT_TIMER: 3600

 

# Keep 5 days worth of reports

REPORT_SHIFT_AGE: 120

 

# Only performance summary and request log

OUTPUT: [perf_summary, txn_log]

6.6    Handling Hung Servers or Requests

 

         Getting insights into the state of an executing thread

 

Very often it is not easy to tell if a request is taking a long time to complete or simply on a “permanent” wait because of a deadlock situation or a programming defect. In these situations, RubyRun supports a global command called cmd_status (refer to Diagnostic Commands in the Appendices section) which shows the status of the Ruby threads and the top frame of the its stack: information that provides insight into the current state and the last method name, file name and line number of the executing thread.

 

         Getting Hung Server/Request

 

To request the Hung Server/Request user needs to issue the command by creating a cmd_status file in the rubyrun directory

 

These commands are repeatable by simply leaving the command in the directory as RubyRun will not remove the command folder/file after its completion.  To stop these commands, the user must manually remove the command file from the “rubyrun” subdirectory.

 

By repeatedly issuing this command over a period of time one can observe if there is any real state change in the suspect thread, confirm the location where the thread is hung on, and decide if further action is needed. These actions may include involving developers to inspect the code, or terminating the thread with a stack trace in case the information provided by cmd_status is not sufficient and a full stack trace is required to diagnose the problem.

 

         Accessing the Hung Server/Request Report

 

To access the following report, you need to go to the report directory and select the thread status file as shown below.

 

rubyrun/report/server__<pid of monitored process>_thread_status.html

 

 

6.7    Terminating Hung Threads

 

RubyRun supports two local commands (cmd_soft_kill_pid and cmd_hard_kill_pid) to enable users to terminate hung threads and attempt to relieve the system from a total lock-up. In this case, the user has to identify the process id for RubyRun to send the command to.

 

         Issuing the command to terminate hung threads

 

Note that either command will terminate the threads in the system by raising an exception, but in the case of cmd_hard_kill_pid, the server process will eventually die as the main thread is also killed. Therefore, it is strongly advised that these commands should only be used as the last resort after all other attempts to resolve the hung situation have been unsuccessful.

 

These two commands will execute once, and RubyRun will subsequently remove the command folder/file after its completion. The user will have to re-create the command file in order to issue it multiple times.

 

Refer to Diagnostic Commands in the Appendices for details of the command and also note the Limitations section regarding using Webrick.

 

         Accessing the thread dump report

 

Issuing this command produces a thread dump report for further analysis. The thread dump report contains the stack traces of all the threads. To access the report, you need to go to the report directory and select the thread dump file as shown below.

 

rubyrun/report/server__<pid of monitored process>_thread_dump.txt

 

 

6.8    Quick Checks for Potential Memory Leaks

 

Memory leaks can be broadly identified by accessing the object map. The object map shows the top 20 active Ruby objects in the heap listed by the number of instances in descending order.

 

         Requesting Object Map

 

To request the Object Map user needs to issue the command by creating a cmd_object_map file in the rubyrun directory.

 

This command is repeatable by simply leaving the command in the “rubyrun” subdirectory as RubyRun will not remove the command folder/file after its completion.  To stop these commands, user has to manually remove the command explicitly.

 

While the cmd_object_map cannot give the root cause of a leak, assuming a stable, loaded environment, it can be used to spot a potential memory leak by repeating this command multiple times over a period of time. This is typically supported by spotting a pattern of monotonic increase in the number of instances of certain application objects. This is especially true since cmd_object_map uses the ObjectSpace.each method to traverse the heap only after issuing a GC call.

 

         Accessing the report

 

To access the following report, you need to go to the report directory and select the object map file as shown below.

 

rubyrun/report/server_<pid of monitored process>_object_map.html

_

 


7      Performance Summary Reports (RSS feed)

 

RubyRun provides three types of reports to help diagnose application performance problems:

 

         Average throughput per minute

         Top 10 slowest Rails requests

         Average Rails request response time by action by controller with breakdown.

 

To enable the performance report, set the OUTPUT option in rubyrun/rubyrun_opts.yml file.

 

OUTPUT: [perf_summary]

 

Putting the perf_summary field enables the performance report.

 

To access the performance report, you need to configure the RSS reader software. Please refer to the section Configuring RSS Reader in appendices for details on how to configure the software.

 

7.1    Average throughput per minute

 

Average throughput per minute is calculated by counting the total number of Rails dynamic requests divided by the number of minutes within the reporting period. The graph depicts the throughput collected at every interval with time stamp.

 

7.2    Top 10 slowest Rails requests

 

Top 10 slowest rails requests chart is based on Average Response Time rankings with the top most bar representing the slowest request.

 

7.3    Average Rails request response time by action by controller with breakdown

 

This report depicts request response time broken into various segments of interest. Refer to the section Understanding Response Time Components for details of what each segment means.

  

 


8      Method Level Trace

 

The Method Level Trace report helps the user show the time spent in various methods of the request. It helps in showing the method flow that happens as part of the request and in diagnosing the time spent in various methods, the number of methods invoked, etc.

 

In the data collection code, metrics such as timings by method by class are collected and stored away in a thread local hash. This data can later be used to serve different functions such as tracing and response time tracking depending on the run time environment and the values of certain properties set in rubyrun_opts.yml. This local data hash will be cleared out when roll up operation takes place due to the end of a request or a thread.

 

         Getting the report

 

To get the report, the user needs to specify TRACE_HASH in the rubyrun_opts.yml file.

 

rubyrun/rubyrun_opts.yml

 

By specifying the TRACE_HASH option, RubyRun traces all the methods of all the classes instrumented.

 

TRACE_HASH: {*: []}

 

For more details about the TRACE_HASH option, refer to the section RubyRun Options file in appendices.

 

         Accessing the report

 

To access the Method Level Trace report, you need to go to the report directory and select the method trace file as shown below.

 

rubyrun/report/server_< pid of monitored process >_trace.html

 

 

 


9      Dynamic Application Discovery (DAD)

 

Dynamic Application Discovery helps the user to know the methods that are dynamically added to the Ruby process.

 

         Getting the report

 

To get the report, the user needs to specify DAD: true in the rubyrun_opts.yml file.

 

rubyrun/rubyrun_opts.yml

 

Set Dynamic Application Discovery to true to log the name of the methods that are dynamically added to the Ruby process.

 

Default value is true: show all the methods added.

 

Example:

# Stop showing added method names

DAD: false

 

         Accessing the DAD information

 

To access the DAD information, you need to go to the logs directory and select the server log file.

 

rubyrun/log/server_< pid of monitored process >.log

 

 


10   Transaction Log

 

The Transaction Log provides details of all the transactions processed by the Ruby on Rails server. This helps in monitoring the transactions processed by the server.

 

         Enabling the report

 

To enable the Transaction Log report the user needs to set the OUTPUT option in rubyrun_opts.yml file.

 

rubyrun/rubyrun_opts.yml

 

OUTPUT: [txn_log]

 

Putting the txn_log field enables the Transaction Log.

 

  • Accessing the report

 

To access the Transaction Log information, you need to go to the report directory and select the server report file. This is a CSV file that can be best visualized using Microsoft Excel or other CSV compatible tools.

 

rubyrun/report/server_< pid of monitored process>_txn_log.csv 

 

 


11  Appendices

11.1     Technical Concepts

11.1.1    Hooks

 

The initial phase of processing of the RubyRun early code involves establishing Ruby callbacks such that RubyRun is notified whenever a method is added. These methods can be instance or singleton; public, private, or protected.

11.1.2    Instrumentation

 

RubyRun uses the proxy method technique to collect performance metrics at the method level.

 

When a method addition is detected, a sequence of decisions will be made to determine if the target method should be instrumented, some based on the values of properties set in rubyrun_opts.yml and some internally.

 

When a method is selected, RubyRun will begin the instrumentation process by creating a proxy method bearing the name of the original method with a layer of code containing instrumentation before relaying back to the original method, which will be renamed via prefixing. Instrumentation only takes place when a class is ‘required’. In a production environment where classes are normally cached, instrumentation should only occur once, while in a development environment where classes are reloaded every time regardless of change multiple instrumentations on the same method will occur.

 

In general developers should only instrument application classes/methods. ‘System’ code such as Ruby or Rails libraries should not be indiscriminately instrumented as this will create undesirable overhead and does not serve any application diagnostic purpose.

 

Instrumentation is also extensible. It is possible, for example, by including additional classes/methods, to extend RubyRun to support non-rails Ruby frameworks such as Merb, and non-proverbial servers such as Glassfish. This is achieved by using the APP_PATHS and INCLUDE_HASH properties.

11.1.3    Logging

 

RubyRun maintains complete logging of its initialization phase, instrumentation phase, and command processing phase.

 

Additionally, RubyRun logs completed Rails requests with response time and breakdown in CSV format.

11.1.4    Tracing

 

One product of the metrics collected from instrumented methods is a forward method trace of a unit of execution (i.e. a Ruby thread). Tracing is an option that can be turned on and off in rubyrun_opts.yml. It is essential for troubleshooting code flow, tuning code and SQL (SQL statements are always traced during tracing), and identifying delay hotspots.

 

Trace output is stored in HTML format for easy viewing.

 

Tracing is applicable for both Ruby and Ruby-on-Rails applications.

11.1.5    Monitoring

 

Monitoring only applies to Ruby-on-Rails applications.

 

Request timings are collected, summarized, and broken down into 6 components according to the RubyRun model of response time decomposition:

 

Monitoring is performed by a separate monitoring Ruby thread and runs on an internal timer (10 seconds). This monitoring thread will execute commands and log incoming requests. Output of other performance metrics is published periodically based on REPORT_TIMER value in the options file. These reports can either be in RSS or CSV format.

11.2     RubyRun Options file (rubyrun_opts.yml)

11.2.1    RubyRun options file

 

rubyrun_opts.yml is the file that allows you to customize RubyRun. By default, the template file is installed as part of the gem install, and a copy of this file is copied over to the “rubyrun” subdirectory, which is created under the current directory of the Ruby process. This copy is the one that gets used by RubyRun at runtime.

 

If there are multiple Ruby processes (such as a Mongrel cluster) in the same OS image serving the same application then they will share the same rubyrun_opts.yml. If there are multiple applications then there should be multiple Ruby processes running on different directories and hence each will have their own rubyrun_opts.yml.

11.2.2    Properties

 

Below are the options in rubyrun_opts.yml and their explanations.

 

APP_PATHS

 

APP_PATHS is an array of directories (absolute path) or a single file from where ruby application code (.rb) is to be loaded. This can simply be a pure Ruby application directory or a Rails controllers’ directory, or a collection of directories where application .rb files reside. RubyRun will recursively expand these directories and open every “.rb” file looking for Class or Module names as target candidates for instrumentation when they are loaded.

 

If RubyRun finds an subdirectory called “app/controllers” the default value of APP_PATHS will be set to the controllers subdirectory. Otherwise the default value is the current directory of the Ruby Process (the one that it is started on).

 

Examples:

 

# Applications in these directories

APP_PATHS: ['/rails_app/diabetes/app/controllers', '/apps/BTSEBE/batch']

 

INCLUDE_HASH

 

INCLUDE_HASH is a hash keyed on class names with an array of method names. Both class name and method name are strings, and names are case insensitive. This hash identifies class/method combinations explicitly that wil be monitored in addition to those found in APP_PATHS.

 

Default value is {}: nothing to include.

 

Examples:

 

# include method_x of any class

INCLUDE_HASH = {*: [method_x]}

 

# include method_1 and method_2 of class AppsClass

INCLUDE_HASH = {AppsClass: [method_1, method_2]}

 

# include all methods of class AppsClass

INCLUDE_HASH = {AppsClass: []}

 

EXCLUDE_HASH

 

EXCLUDE_HASH is a hash keyed on class names with an array of method names. Both class name and method name are strings. Names are case insensitive. This hash identifies class/method combinations to be excluded from instrumentation. This can be used to exclude certain application classes/methods from the instrumentation candidates automatically identified by APP_PATHS.

 

Default value is {}: nothing to exclude.

 

Examples:

 

# nothing to exclude

EXCLUDE_HASH = {}

 

# exclude method_x of any class

EXCLUDE_HASH = {*: [method_x]}

 

# exclude method_1 and method_2 of class AppsClass

EXCLUDE_HASH = {AppsClass: [method_1, method_2]}

 

# exclude all methods of class AppsClass

EXCLUDE_HASH = {AppsClass: []}

 

TRACE_HASH

 

TRACE_HASH is a hash keyed on class names with an array of method names. Both class name and method name are strings. Names are case insensitive. This hash identifies class/method combinations explicitly to be included in method tracing, assuming they have been instrumented.

 

For Rails application performance testing or running in a production environment, tracing can degrade performance in terms of response time delay and CPU overhead, and is a largely determined  by how many methods have actually been instrumented. For a long running Ruby applications the amount of trace data can also be very large.

 

Default value is {}: no tracing.

 

Examples:

 

# Stop tracing

TRACE_HASH: {}

 

# Trace all instrumented methods

TRACE_HASH: {*: []}

 

# Trace only method1 and method2 of Class1, and method3 and method4 of Class2

TRACE_HASH: {Class1: [method1, method2], Class2: [method3, method4]}

 

DEBUG_ARGS

 

Set DEBUG_ARGS to true to trace values of arguments at method entry (via the inspect method) for instrumented methods. This can slow down execution and affect memory footprint if large objects are passed around frequently.

 

Default value is false: do not show arguments.

 

Example:

 

# Show the inspected arguments at method entry

DEBUG_ARGS: true

 

DEBUG_OBJ

 

Use DEBUG_OBJ to trace the object (via the inspect method) that made the call to the instrumented method. This can slow down execution and affect memory footprint if method calls are frequently made by large objects.  

 

Default value is false: only show the class name of the calling object.

 

Example:

 

# Show the entire inspected calling object

DEBUG_OBJ: true

 

DAD

 

Set Dynamic Application Discovery to true to log the name of the methods that are dynamically added to the Ruby process.

 

Default value is true: show all the methods added.

 

Example:

 

# Stop showing added method names

DAD: false

 

REPORT_TIMER

 

REPORT_TIMER is expressed in seconds. It is used by the monitor thread to determine how frequently to generate performance reports. The value must be between 60 and 3600.

 

Default value is 60.

 

Example:

 

# Generate reports every hour

REPORT_TIMER: 3600

 

REPORT_SHIFT_AGE

 

Set the maximum number of RSS items to be kept by RubyRun before the oldest item is shifted and purged. The value must be between 1 and 120.

 

Default value is 60: keep 60 copies of reports

 

Example:

 

# Keep reports for 5 days, assuming one report per hour

REPORT_SHIFT_AGE: 120

 

OUTPUT

 

Choose the types of reports. The following options are available:

 

1.      perf_summary – Performance summary in RSS format

2.      txn_log – Transaction log in CSV format

 

Default value is [perf_summary, txn_log]

 

Example:

 

# Only performance summary

OUTPUT: [perf_summary]

 

RSS_PATH

 

Set the location of the RSS channel and item files. This option is only relevant if perf_summary is chosen in the OUTPUT property.

 

Default is blank and RubyRun will use [application directory]/public/rubyrun_rss as the RSS output directory.

11.3     Diagnostic Commands

 

The RubyRun monitoring thread supports commands which can be issued at run-time. These commands are useful for detecting potential memory leaks or identifying and resolving transaction hang situations. They are responded to by the monitoring thread within 10 seconds.

 

You can place multiple commands in the “rubyrun” subdirectory.

11.3.1    Local commands

 

Local commands only affect a specific RubyRun process (a Ruby process running with RubyRun)

 

To issue a local RubyRun command, create a folder or file in the “rubyrun” subdirectory with one of the following names. Note the pid (process identifier) as the suffix of the command folder/file. This pid identifies the Ruby process to which you are sending the command.

 

These command folders/files will be removed by RubyRun after the command’s completion. To repeat these commands they will have to be re-created explicitly.

 

cmd_soft_kill_pid

 

The soft-kill raises a signal to all the threads in the Ruby process except the main thread, the running thread, and the monitor thread, causing them to abort with a full stack trace (before raising a signal, RubyRun also shows the status and top stack frame of the target threads).

 

cmd_hard_kill_pid

 

Similar to cmd_soft_kill, cmd_hard_kill raises a signal to all the threads in the Ruby process including the main thread, causing them to abort with a full stack trace. In cmd_hard_kill, the process will finally collapse as the main thread terminates.

11.3.2    Global commands

 

Global commands affect all RubyRun processes.

 

To issue a local RubyRun command, create a folder or file in the “rubyrun” subdirectory with one of the following names.

 

These command folders/files will NOT be removed by RubyRun after its completion and hence readily repeatable by the monitor thread when its timer pops (10 seconds) next time. To stop these commands they will have to be removed explicitly by the user.

 

cmd_object_map

 

The top 20 active Ruby objects in the heap are listed by the number of instances, in descending order, after a GC call has been made.

 

cmd_status

 

View the status and the top stack frame of all the threads inside the Ruby process, including the current file and line number and function.

 

11.4     Configuring RSS Readers

 

Using Firefox as a RSS reader

 

  1. Start Firefox and open the URL http://[host]:[port]/rubyrun_rss/perf_summary.xml where:

[host] is hostname of the monitored Rails application

[port] is the port number used by the Rails application

 

  1. Press Subscribe Now button to subscribe the performance summary RSS feed. See the screenshot below:

 

 

 

  1. A RubyRun live bookmark is created. You can select and view the performance reports by pressing the bookmark button. See the screenshot below:

 

 

Using Internet Explorer 7 as a RSS reader

 

  1. Start Internet Explorer and open the URL http://[host]:[port]/rubyrun_rss/perf_summary.xml where:

[host] is hostname of the monitored Rails application

[port] is the port number used by the Rails application

 

  1. Click the link Subscribe to this feed to subscribe the performance summary RSS feed. See the figure below:

 

 

  1. A RubyRun RSS feed is created in the Favorites Center. You can select and view the performance reports by clicking the link. See the figure below:

 

 

Using Microsoft Outlook as a RSS reader

 

  1. On the Tools menu, click Account Settings.

 

  1. On the RSS Feeds tab, click New.

 

  1. In the New RSS Feed dialog box, type http://[host]:[port]/rubyrun_rss/perf_summary.xml where:

 

  1. [host] is hostname of the monitored Rails application

 

  1. [port] is the port number used by the Rails application

 

  1. Click Add.

 

  1. Click OK.

 

  1. A RubyRun RSS feed is created in the RSS Feeds folder. You can select and view the performance reports by clicking the feed. See the screenshot below:

 

 

11.5     Lab Tested Platforms and Servers

 

The following platforms have been tested in the Rubysophic lab.

 

  • Windows XP

 

  • Windows Vista

 

  • Redhat

 

  • Mac OS X Tiger and Leopard

 

  • Mongrel

 

  • Webrick

 

  • Rails V1 and V2

11.6     Performance

 

Internal measurements conducted in the lab to assess the overhead of RubyRun in terms of response time shows a range of degradation between 4ms and 35ms on a variety of Rails requests. Such degradations will drop further if RubyRun is run on more powerful servers or CPUs with a higher speed. These tests were performed under the following environment and settings:

 

  • A 1.6Gz DualCore computer

 

  • Redmine 2.1

 

  • Rails 2.1

 

  • Mongrel

 

  • Windows Vista

 

  • RubyRunCE V0.9

 

  • Instrumentation scope in rubyrun_opts.yml:

 

Ø  APP_PATHS limited to app/controllers

 

Ø  INCLUDE_HASH and EXCLUDE_HASH are empty