00:00:12.599
Hi Australia! How are you doing? So far, there have been a lot of amazing presentations today, and I hope this one is one of them too. It's my first talk ever at a conference, and I'm pretty excited as well as somewhat nervous. Thank you for the support!
00:00:32.079
I'm going to be talking about performance optimization in Ruby and how to do simple things that make your app run faster. Before we go any further, I should mention that I’m new to Australia, and Melbourne. Speaking of Melbourne, the weather has been quite unpredictable—chilly in the morning, yet now it's hot again! The weather here changes faster than the code I write—just kidding! My code runs fast too!
00:01:20.431
I added this slide because I learned that you can add emojis to presentations yesterday, and I just wanted to give it a go. A bit about myself—I’m a computer science undergrad and have assisted hundreds of Ruby applications in fixing performance bottlenecks. You might be familiar with Celluloid, which is one of my notable works—it's a concurrency framework for Ruby. Last summer, I worked on it and managed to make it around 300% faster, which I think is pretty substantial!
00:02:04.240
Most of the tips I’m going to share are based on my experience optimizing Celluloid. So, what exactly is performance optimization? You might be a new venture-funded unicorn that views performance optimization as simply spinning up more dynos in Heroku, but is it really that simple? To me, performance optimization means doing more with fewer resources, which can be somewhat counterintuitive to scaling.
00:02:50.799
Don't get me wrong; there are times when you do need more servers. However, throwing more servers at bloated, slow code won't resolve the underlying problems—you eventually need to improve performance. So, how exactly do you optimize? Here are six tips you can try to make your app run faster.
00:03:16.480
Tip number one: always have a benchmarking suite. When developing a program, one of the last steps should be to ensure it is as fast as possible. I've seen many apps without benchmarking suites where a developer makes a change and, for some reason, it runs faster for a moment. They then jump from their chair and run to their project manager, exclaiming they've made the site faster! Without a benchmarking suite, you really can’t claim any performance improvements.
00:03:53.760
So, a benchmarking suite is absolutely necessary. Benchmarking IPS is one amazing tool I use often; it tells you how many times a function can be called per second. For example, with the Benchmark IPS Gem, this code calculates how many times two numbers can be added in a second. It shows you how many times a function can run per second. If you run it, you will get results indicating that I can add one and two approximately 12.5 million times per second, which is pretty fast! However, there is always room for improvement.
00:04:58.840
Tip number two: upgrade your Ruby version. I met someone yesterday who was still using Ruby 1.8—they were too busy writing new features to upgrade deprecated methods! For anyone still running on 1.8, please upgrade to 1.9! You will be amazed by the performance improvements it offers. Ruby 2.0 has a feature called copy-on-write, which optimizes memory usage by allowing sharing of memory between parent and child processes until one of them modifies the data.
00:05:32.520
Moreover, Ruby's garbage collection has been a challenge for some time, but with Ruby 2.1, we introduced Generation Garbage Collection, which partitions heap space into young and old scopes to improve efficiency. Each iteration reduces the heap data to scan through, making Ruby perform faster overall.
00:06:11.279
Moving forward, tip number three: try another implementation of Ruby. You can benchmark your application on different versions; for example, JRuby offers faster performance for calculations than MRI. However, it comes with some shortcomings due to JVM overhead. Use a benchmarking suite to find out which Ruby implementation works best for your application.
00:06:45.760
Here's a benchmark comparing Ruby 2.3 and JRuby. While I mentioned 12.4 million times faster on its own, JRuby can perform calculations at nearly twice that speed in roughly the same time. Another interesting Ruby implementation currently in development is JRuby with Truffle, which claims to be 31% faster than Ruby 2.3.
00:07:58.160
Moving to tip four: always profile your methods. Profiling helps pinpoint the lowest-hanging fruits to improve app performance. I’ll show you some tools later on, so hang tight! Tip five: when generating your benchmarking suite, identify potential bottlenecks. Understanding why your code runs slowly will save you time—optimize the functions that are rarely used, not the ones that are called frequently.
00:09:01.400
You need to determine where the majority of processing time is spent. Is it I/O operations or excessive CPU calculations? Here comes tip six: consider multi-threading. This can greatly improve performance, especially relevant in discussions around actors and Celluloid. If you're not a fan of Elixir, I'd recommend trying Celluloid as it significantly enhances application performance.
00:10:19.680
As for implementations of Ruby with Celluloid, try JRuby or Rubinius, as both are well supported. Now, let’s shift to some tools I frequently use. The first tool is the Method Profiler, which collects performance information about methods in your objects and creates detailed reports regarding execution times. This is directly tied to the previous tip.
00:12:06.720
Next, we have Kcachegrind, a call graph viewer that provides advanced insights by telling you how much CPU time each method consumes, using a GUI to visualize this information. If you are on MRI, you won’t see values over 100%, but multi-threading can higher those numbers.
00:13:14.759
Another useful tool is Ruby Prof. It allows you to easily visualize which parts of your code are running slowly by breaking down your program's performance per thread. For example, you might find that a certain method is utilizing 99.9% of CPU time.
00:13:49.919
Moving on, ObjectSpace counts objects, helping with memory optimization by checking the number of objects created before and after specific code execution. By disabling garbage collection before running your code, you can examine the spike in object creation, allowing you to fine-tune your memory usage.
00:15:06.519
Lastly, there's Drace, which I've heard is great for real-time CPU monitoring. While I have not personally used it, it's been recommended as a definitive tool for such monitoring tasks, so you may want to consider trying it!
00:15:46.880
Thank you all very much for being here at RubyConf AU! I hope you're having a great time!
00:17:00.000
Do we have a couple of minutes for questions? Does anyone have any specific questions?
00:17:17.280
Speaker answers questions regarding Rubinius and JRuby, clarifying that the goal is to optimize both frameworks, with a focus on collaboration with the Rubinius core team. Thank you!