GoRuCo 2016

Micro Talk: Ruby Racing - Challenging Ruby Methods

Ruby Racing: Challenging Ruby Methods Danielle Adams

Ruby is widely-used and prides itself on "simplicity and productivity". But what is happening under the hood of our favorite programming language? Are there better, faster, or stronger ways to implement these methods? I'm going to take a deep, yet brief, dive into testing and optimizing some of Ruby's most popularly convenient methods.

Help us caption & translate this video!

http://amara.org/v/Prkd/

GoRuCo 2016

00:00:13.850 I know I'm the last thing before lunch, so I will try to make this quick. I'm very hungry, as I'm sure you are. My name is Danielle Adams, and I am a software engineer at a company called Blue Apron, where I lead our warehouse team in converting millions of raw produce into meals across the country. Today, I'm going to talk about Ruby racing, so let's get started.
00:00:37.430 Show of hands: how many of you are programmers here? Excellent, me too! How many of you write in Ruby? Cool! How many of you write primarily in Ruby every day? Awesome, that's a good ratio. Now, how many of you would say that you are absolutely confident that your code is running as quickly as it could? Just one person? Awesome! That’s okay; as developers, we have a lot to do.
00:01:06.470 We're writing code, involved in version control, pushing our code to GitHub, deploying it, ensuring our apps and tests don’t break, and so on. It’s natural to trust what we're used to, including the open-source software we're using, like Ruby. Ruby was designed to make us happy, and it isn’t something we’ve been trained to scrutinize. So just by looking at this, can anybody tell me what this method is? Preferably, someone who is not part of the Ruby core team, as they probably know.
00:01:40.700 So, who can tell me what method this is? 2s! Good work! Much smaller and much simpler. This is why we love Ruby because we don't want to write a block of code just to convert something into a string. To give you a little background on how Ruby methods work: we write our code, save it to a file (like my_code.rb), and this is converted into tokens, which are then parsed into an abstract syntax tree.
00:02:15.860 To us, it might look like nested arrays, but it's actually a tree structure. This tree structure is converted into bytecode. Since Ruby 1.9, we're using bytecode that is interpreted by the Ruby MVM, which stands for 'Yet Another Ruby VM.' It's a tongue twister! What does that mean? It seems kind of simple, but we don’t often think about it—at least I didn’t until I started investigating.
00:02:45.750 This talk came about through conversations with my coworkers about how to make our code faster. We were brainstorming different ways to do it on a whiteboard, discussing which code was better, shorter, or more readable. We decided to put it to the test. First, we created RSpec tests to ensure the code was functioning properly, and then we benchmarked it to measure its speed.
00:03:10.590 To our surprise, we discovered that some of the Ruby code we wrote was actually faster than its C implementation. I went home astonished and started looking for patterns in Ruby methods that I could implement myself. I rewrote a number of array methods, focusing specifically on easily measurable input and output, and found that I could indeed make some Ruby code perform faster.
00:03:40.200 Thus, I created an open-source project, which includes a little game. The game allows you to input your implementations of Ruby methods. As of now, it works with various types of methods, like string and array methods. If you discover any limitations, come find me!
00:04:11.310 Now, I would like to demonstrate how this works. First, I started with Ruby's sort method, which employs a quick-sort algorithm. I attempted to implement this in Ruby, but while it was shorter, it didn’t outperform Ruby’s own sort. Next, I tried the sample method, which selects random elements. However, that didn’t yield the performance I desired either.
00:04:36.180 Then, I tried the unique method, and it was faster. Following this, I worked on the max method and found that I was also able to improve its speed. Naturally, since I was modifying max, I also tried to implement min with a similar algorithm.
00:05:03.480 To give you an idea of how I implemented these methods: my version of max utilized a simple while loop that iterated through the array, selecting the highest number and returning it. It was straightforward. The unique method was slightly more complex—also employing a while loop.
00:05:35.780 I believe that using a while loop was key in speeding up the Ruby methods. I also rewrote my own version of the contain method using a while loop, which wasn’t the most optimal, but it worked and was faster.
00:06:02.699 Things to note about this process: the input I provided does not necessarily guarantee that it's the most optimal execution. Ruby handles a range of scenarios—from best-case to worst-case—while my small implementations assume the programmer will input smartly, which may not always be the case.
00:06:30.840 My methodology for benchmarking may also differ; I calculated the average runtime by measuring the difference in time taken to execute 50,000 iterations. Efficiency, as I see it, is primarily measured by time. However, efficiency could also pertain to memory use, scalability, or readability. There are many ways to assess code efficiency.
00:07:05.590 Resources for those with a Python background: you might recognize the language called PyPI. It was implemented to rewrite parts of the Python language, and it’s proven to be faster than the original. I highly recommend the book 'Ruby Under a Microscope' by Pat Shaughnessy, which excellently explains what happens under the hood with Ruby code.
00:07:35.050 I found it interesting to discover that my curiosity and discussions with coworkers led me to explore these topics, as it is not something I would have pursued alone. Additionally, I've looked at the Ruby source code to understand how it works, which is not something everyone does.
00:08:06.530 So, why should you care? You might not, and that’s okay! But I want you to understand that we may not take full advantage of what Ruby offers. It's important to think about how it works under the hood and not to simply trust that it provides the most efficient or rapid methods. It's okay to question that.
00:08:36.180 I encourage you to explore and experiment with Ruby. You can install the gem 'Ruby Racer' to follow along with the examples provided in the readme. If you have any questions, feel free to reach out to me via Twitter or email.
00:09:02.960 In conclusion, if you take away anything from this talk, I hope it’s a cute picture of a puppy! I adore puppies! But beyond that, I hope you leave with a sense of curiosity about your Ruby code and what’s happening behind the scenes.
00:09:28.430 I encourage you to break things apart and put them back together. Be curious!