00:00:14.460
Hello, everyone! Can everybody hear me? Yes? No? Thumbs up? I can't tell. Woo! All right. Um, hey everyone.
00:00:22.210
Good morning! I want to thank the GoRuCo organizers, especially NYC Ruby.
00:00:30.160
My first meetup was probably in 2005, which is a long time ago now. This is my first time doing a full-length presentation at GoRuCo. Last year, I gave a short talk, but I dropped my iPhone off a boat, so I think Francis and Josh felt bad and that's why I'm here today.
00:00:41.860
Maybe it's because of something else, but regardless, I want to talk about Ruby performance today.
00:00:50.199
I've spent a lot of time thinking about and working on Ruby performance at Paperless Post. We are a platform for delivering important messages online and offline, and we have a great team of talented designers and developers, as well as really good eaters!
00:01:04.299
Today's agenda is more practical. I've been working hard on some interesting things, and I want to share that practical work with you. But first, let’s start with some philosophy.
00:01:16.360
The reason I want to talk today is that performance matters. This phrase gets repeated often, but not everyone addresses why. When we refer to performance, most people are concerned with user experience metrics, like time to first byte and how quickly pages load.
00:01:28.929
These factors significantly impact user experience on your website. From my experience leading a team and working with our operations team in a scrappy startup, performance is also about dollars and cents.
00:01:41.009
The faster your application runs, the fewer servers you need to operate it, resulting in real cost savings.
00:01:50.199
Unfortunately, Ruby's performance doesn't often get talked about positively. However, since this is a Ruby conference, I shouldn’t have to defend Ruby’s worth.
00:02:00.249
When discussing performance, I'm mainly referring to web applications, whether you're running an iPhone app or something similar.
00:02:13.120
I want to illustrate a typical web app request. Imagine your user, who spends time connecting to your server, while your application builds the page.
00:02:25.870
This typically takes 10 to 30 milliseconds, depending on your Ruby processing time.
00:02:39.310
Once the page is built, time elapses while CSS, JavaScript, and images are downloaded. The time it takes for the user to see anything is marked by a dotted line.
00:02:49.390
As developers and operators, we can control certain aspects like how quickly HTML and assets download.
00:02:58.570
However, the crux of the timing issue lies in how long it takes to generate our page on the server.
00:03:10.570
The bulk of the page generation time usually comes from our application code, a significant portion from the database, and possibly from Rails itself.
00:03:22.670
Where do we start to improve performance? In the past, Ruby has suffered due to a lack of focus on operator needs rather than just developer ease.
00:03:35.690
Initially, many features in Ruby and Rails have focused on development speed and not the performance of the final application.
00:03:48.840
However, we have seen a real shift. Last year, several major operators, particularly from GitHub, were given commit access to Ruby.
00:04:00.140
This shift has spurred efforts to improve Ruby's introspection capabilities, which is essential for improving performance.
00:04:12.570
I'm happy to report that Ruby now has APIs to build tools for introspection, which is particularly valuable for operators of large Ruby applications.
00:04:23.560
Today, I’ll give an overview of Ruby performance tooling and some of the new features we can leverage.
00:04:34.500
I’m excited about the potential improvements in Ruby performance tooling.
00:04:40.350
I want to discuss various tools that can track how your application performs. If you aren't using these tools, you're essentially flying blind.
00:04:50.140
It's important to note that there is no single tool that acts as a silver bullet for fixing all performance issues.
00:04:57.530
The reality is that effective Ruby performance management requires a combination of different tools for various situations.
00:05:04.670
I’ve devised a system to categorize Ruby performance tools using what I liken to a D&D scoring system for performance tools.
00:05:12.350
I'll begin with ActiveSupport Notifications. I like to call these the elves of the Ruby performance landscape.
00:05:20.310
ActiveSupport Notifications, introduced in Rails 3, allows you to publish events and collect metrics.
00:05:27.170
This functionality is not just limited to Rails applications, making it widely usable.
00:05:34.000
It essentially tracks the time for specific blocks of code, giving you a way to benchmark performance.
00:05:40.500
However, the performance impact of using ActiveSupport Notifications can vary depending on the level of detail you want.
00:05:48.120
The more specific you aim to be in tracking actions, the more impact you'll have on performance.
00:05:54.760
For operator ease, it's relatively simple to set up, and the readability of the output hinges on how you format the data.
00:06:01.670
For example, if you generate graphs to visualize the data, it's wonderfully insightful.
00:06:07.540
Overall, it’s very effective for monitoring the 90th percentile of your application's performance.
00:06:14.370
Next, I want to talk about rblineprof, which I refer to as the warrior of performance profiling.
00:06:20.230
This tool, developed by Amon, is a first-class line profiler and stands out because it effectively identifies line-level performance issues.
00:06:28.670
Robust line profiling was something that Ruby had lacked for a long time, but this tool changes that.
00:06:37.650
When you wrap a block of your application code, rblineprof will collect detailed execution times per line.
00:06:45.360
This visibility into each line of code is vital for identifying sections that slow down your application.
00:06:54.780
Like other profiling tools, it's not recommended for use in production due to its overhead.
00:07:00.310
After discussing rblineprof, let’s proceed to pp_profiler, which acts as a wrapper around other profiling tools.
00:07:06.630
PP Profiler can run specific code repeatedly while collecting benchmarks of execution time for both cached and non-cached runs.
00:07:12.840
Because it outputs results in markdown format, it's easy to share the results with the team.
00:07:20.270
This tool is specifically designed for local development and is not suitable for production.
00:07:26.360
By tracking local improvements, such as refactoring code and measuring changes, it fosters collaboration among team members.
00:07:35.320
Finally, I want to highlight StackProf, which I consider to be magical.
00:07:43.560
StackProf is a sampling profiler that allows you to gather performance metrics without impacting application performance significantly.
00:07:48.360
It helps identify hotspots in your application and provides visibility into what methods consume the most time.
00:07:55.070
Brendan Gregg has popularized the concept of flame graphs, which visualize this sampling data effectively.
00:08:00.450
By analyzing these flame graphs, you can see where time is being spent in your application.
00:08:09.270
This is particularly useful for diagnosing systemic issues in production.
00:08:14.520
However, the tool is less effective in revealing explicit details about what is making your code slow.
00:08:23.500
We want to reach a point where we can introspect our production environment effectively.
00:08:30.360
As I mentioned, I've been influenced by concepts I've seen while working with Go tooling.
00:08:39.870
In Go, including middleware in your HTTP server generates performance metrics easily.
00:08:46.720
This has inspired me to think about how we can implement similar functionalities within Ruby.
00:08:55.270
The ability to introspect performance in production is incredibly valuable.
00:09:00.800
By using tools like rbtrace and StackProf, we can achieve significant insights regarding our code.
00:09:06.320
I hope to illustrate how effective introspection can lead to an enhancement in our production environment.
00:09:15.190
I also want to touch upon the new generational garbage collection in Ruby.
00:09:23.580
Recent updates have introduced features like ObjectSpace and the ability to dump memory states.
00:09:30.210
This level of introspection lets us explore object allocations in our applications.
00:09:36.040
By utilizing ObjectSpace's abilities, we can identify memory leaks and optimize the memory footprint of our applications.
00:09:44.570
While this tool is powerful, it can cause performance overhead when used in a production environment.
00:09:52.000
However, it opens a host of opportunities for diagnosing and correcting memory issues.
00:09:57.360
I believe that by combining these approaches, we can bring Ruby performance tooling into a new era.
00:10:06.320
With proper introspection, developers can gain the understanding needed to drive impactful performance improvements.
00:10:13.590
Ultimately, the message I want to convey is that Ruby performance tooling is evolving.
00:10:20.610
And that's crucial, especially as we continue to push for advancements in our Ruby applications.
00:10:27.860
Thank you very much for your time! Here's a link to my GitHub, where you can find some of the projects I've mentioned.
00:10:35.160
If you have any questions or want to discuss further, please find me afterwards. Now that I'm done, I'm looking forward to unwinding!
00:10:43.760
Let’s hang out and chat more about Ruby performance tooling. Thank you!