00:00:09.620
Hello everyone! Today, I'm going to talk about debugging Ruby. The slides are available on SlideShare at bit.ly/flash-debugging-ruby, so feel free to follow along.
00:00:16.680
My name is Aman Gupta, and I go by 'Tim m1' on GitHub and Twitter. I enjoy writing Ruby code, but as many of you may have experienced, it can lead to a few challenges.
00:00:28.289
One common issue is dealing with nasty bugs and slow performance. Ruby is often criticized for its sluggishness, particularly due to source flow and memory consumption. This talk will address tools available to help you tackle these issues.
00:00:40.800
We will discuss various tools that can aid in debugging Ruby applications. Specifically, I will cover tools available on Linux since many of us develop on that platform. Understanding tools for C code is essential, as the MRI Ruby interpreter and many extensions are written in C. Also, I will touch upon tools for network analysis as most web applications interact with services and databases.
00:01:04.199
Additionally, it is important to have tools to analyze CPU and memory usage, as these factors ultimately determine how scalable our Ruby applications can be and how much they will cost to maintain. Before diving into these tools, I want to mention that many of these slides contain detailed descriptions on how to get started with various command-line options and flags that I will gloss over.
00:01:23.520
What I want you to focus on are the use cases of these tools—specifically, their utilities, when to use them, and why to use them. When you find a reason to use these tools, you can refer back to the slides later for command details.
00:01:38.700
The first tool I want to introduce is 'lsof,' which is available on Mac and Linux. It is essentially used to list open files. You only need to run this command on any process. The unique aspect of this tool is that you can attach it to any running process, Ruby or not, and get an overview of what it's doing. I usually run it first to get a high-level view of the active processes.
00:02:08.660
When you run 'lsof,' you might see output that includes shared libraries being loaded, such as the JSON or Memcache libraries. Furthermore, it displays all the open files and sockets, highlighting connections to services like MySQL or Memcache. You can also see incoming HTTP connections, which is particularly helpful when diagnosing web applications.
00:02:51.170
Another noteworthy detail is the current working directory of your Rails application and other files related to its execution. The ability to visualize all this information can help you understand the context of your Ruby application's behavior more clearly.
00:03:32.840
Next, I want to talk about 'strace,' a powerful tool for tracing system calls and signals. System calls are functions defined in the kernel. When you make a system call, control switches from user space to kernel space, allowing you to execute kernel-defined functions. What’s particularly cool about 'strace' is that you can run it against any running process by providing its PID.
00:04:03.560
'strace' prints system calls in real-time, allowing you to observe exactly which functions are being called. You can use 'strace' in summary mode with a specific flag to get an overview of which calls occurred most frequently during a given time. Depending on the process being analyzed, this can reveal significant insights about how your application is interacting with the system.
00:04:54.710
In its normal tracing mode, 'strace' providesDetailed information about every single system call executed by the process. For example, in a Rails application, you might notice that most time is spent in read operations, particularly from MySQL or web service calls.
00:05:18.540
I frequently use 'strace' to identify performance issues in production Ruby instances. For instance, I implemented 'strace' on a Rails application that had an unusual number of signal interruptions, which led me to investigate the underlying cause more deeply.
00:05:32.740
Upon investigation, I discovered that Ruby's green threads utilize the SIGALRM signal to manage them, causing unnecessary signal interruption even when threads were not in use. I devised a patch to address this issue, which was accepted and will be included in Ruby 1.8.8.
00:06:01.620
Another significant discovery was that a lot of calls to a function named 'rt' were happening due to the way Ruby was compiled on various distributions. This led to a performance slowdown that prompted me to submit another patch, now included in Ruby 1.8.8. It demonstrates how even small changes can lead to significant improvements when examining software performance.
00:06:24.619
Moving forward, I want to introduce 'tcpdump,' which is essential for analyzing network activity. This tool allows you to specify an expression that filters the types of network traffic you want to monitor, which is particularly useful given that most applications interact with various network services.
00:07:08.100
'tcpdump' can capture traffic, including HTTP requests, and save it to a file for further analysis. You can load this data into 'Wireshark,' a graphical tool for analyzing network protocols. It provides clear insights about network interactions, making it easier to understand, debug, and optimize network delays.
00:08:20.600
Next, I want to mention 'perf tools,' which originated from Google. This set of tools is designed for profiling and tracing applications, and it offers a shared library that can be linked or preloaded into your Ruby application. By configuring the relevant environment variables, you can generate performance profiles of your code.
00:09:05.800
'perf tools' provides graphical outputs that showcase the functions where time is being spent within your application, allowing you to easily identify slowdowns. I’ve used it on various Ruby projects, leading to improvements in CPU efficiency by changing the way we managed how time was parsed.
00:09:30.210
Additionally, I wanted the profiling to focus on Ruby functions instead of just C functions, which led me to create a project called 'rbperf' that incorporates Ruby function tracking into the profiling process.
00:10:05.400
Moving to the next tool, I want to discuss 'memory profiling.' This tool analyzes object allocations in Ruby applications, making it easy to identify where excess memory usage occurs. For instance, I've employed that memory profiler to determine that significant time was spent in string manipulations, leading to unnecessary object allocations.
00:10:40.500
By identifying heavy memory operation overlaps, I was able to drive significant performance improvements in multiple applications. Furthermore, 'memory profilers' help visualize what types of objects are being created, leading to insights on optimizing memory management.
00:11:25.900
Another recent tool I used is 'tprof,' which analyzes Ruby objects to see where memory leaks are occurring. It shows how many objects remain in memory, enabling you to pinpoint which parts of your code might be responsible for unexpected object retention.
00:12:00.800
To utilize this effectively, you must install a patched version of Ruby. However, it provides valuable insight into where your application may not be releasing memory appropriately.
00:12:35.570
Now, I want to call attention to 'kcachegrind,' which visualizes profiling data for better understanding. Combine this with tools we've discussed today, and you will be equipped to address most performance issues within Ruby applications.
00:13:00.800
Lastly, I recommend using 'gdb,' the GNU debugger, to assist in identifying segmentation faults that may arise in Ruby applications. It allows you to attach to a process, analyze its stack trace at the point of failure, and understand where the problem might stem from.
00:14:00.300
With these tools and techniques today, you can refine your debugging process in Ruby significantly. Always remember that effective debugging starts with understanding what tools are available to you.
00:14:40.300
If you're having trouble identifying performance bottlenecks, reach out to the Ruby community for insights. They’ve valuable tools and experiences that can assist you in optimizing your applications.