Talks

Using Rust with Ruby

Ruby is a wonderful language, but sometimes, you need a little extra oomph. While C extensions are a great way to improve performance-sensitive parts of your application, you can use other languages too. In this talk, Steve will show off the Rust programming language and how to integrate it with Ruby. Rust is a systems language focused on safety, speed, and concurrency, and compliments Ruby nicely.

Ancient City Ruby 2016

00:00:00.060 Hello, everyone! My name is Steve Klabnik, and I'm excited to be here today. I hope you're all doing well. Before we get started, here's my Twitter handle, which you probably shouldn't follow.
00:00:12.750 Today, I will be discussing two programming languages that are very dear to my heart: Ruby and Rust, and how we can make the two play together. I like to joke that I only work in languages that start with 'Ru' nowadays.
00:00:31.590 In this presentation, I've decided to use a different approach. I've created slides using raw Markdown files because, as programmers, we often work with such files. I'll show you a bunch of code, starting with the slides before transitioning into the code.
00:01:07.860 We have a few different topics to cover today. The first is the concept of systems programming, which is often misunderstood. The second topic is Rust, as it relates closely to this context, and finally, we'll look at Rust's interaction with Ruby. While I've given similar talks at Node and Python conferences, today, I'll primarily focus on Ruby, although the fundamentals apply to any programming language.
00:01:42.509 So let's start with systems programming. There is a lot of confusion surrounding the term, and people often misunderstand or argue about it. Words can indeed be tricky! I like a definition by Yehuda Katz, which states that systems programming is when it actually matters. This definition might seem nonsensical, but it resonates well with me.
00:02:13.400 In the Ruby world, we frequently discuss how many things don’t really matter in most cases. For example, while Ruby is often criticized for being slow, we can argue that the database and network are slower processes. Thus, it doesn't matter that Ruby is somewhat slow—it is fast enough for most applications. Memory use can also be a concern, but with services like Amazon, memory is relatively inexpensive.
00:02:52.459 However, in certain applications or software, things do matter. Sometimes, specific memory usage is crucial, or speed is imperative. For instance, a two-week process versus a one-week process can significantly impact operations. This is why control over various aspects becomes so important.
00:03:14.090 People often think of systems programming as something dominated by C and bearded individuals who are rather unfriendly. This mythologizing of low-level programming gives people the impression that it is inherently harder or that those who engage in it are superior to others who primarily use languages like Ruby or JavaScript. The reality is that everyone excels in different areas.
00:03:35.090 I know many experienced programmers who find low-level programming easier than web programming. When you speak to them about assembly instructions, they appreciate how straightforward they are. On the contrary, web programming—which combines multiple languages and technologies—is incredibly complex.
00:04:01.430 Don’t be discouraged if you haven’t tried lower-level programming before. It's essential not to listen to those who tell you it's hard because it may be that it’s hard for them and not for you. Rust and its community aim to assist those unfamiliar with low-level programming, making it a welcoming place for learners who want Rust to be their first experience in this area.
00:04:49.380 As you explore Rust, you might discover that it not only improves your skills but also enhances your capabilities in Ruby. Rust is a systems programming language that focuses on three key areas: safety, speed, and concurrency. One way to conceptualize programming languages is through a trade-off between speed and safety.
00:05:26.610 Languages like C are generally very fast but also potentially dangerous to use. You have an extreme level of control, but with that comes the risk of making significant errors. Ruby, on the other hand, offers a safer experience, as you can’t typically face segmentation faults unless you’re using native extensions, which can still be somewhat tricky.
00:06:01.000 Java sits somewhere in the middle, often criticized but offering a blend of safety and speed. The goal of Rust is to balance these attributes by providing a language that maintains Ruby's safety while achieving or surpassing C's speed.
00:07:02.400 Achieving this balance entails making several compile-time checks that can sometimes feel challenging for newcomers. While Rust's compiler does a lot of work for you, it can occasionally feel like a frustrating experience, leading people to liken it to fighting with the compiler.
00:07:57.990 In my experience, that interaction with the compiler feels more like a helpful friend warning you against making a mistake.
00:08:43.500 While I intend to show you some Rust code, this talk is more about integrating Ruby with this exciting language. For instance, I often have to prepare a second terminal window while transitioning between code samples.
00:09:27.080 To integrate Ruby and Rust effectively, we need to connect them in a way that allows Ruby to communicate with Rust, which often pretends to be C. This translates into some interesting techniques, allowing us to convert Ruby elements into C so that Rust can understand them.
00:10:17.660 For demonstration purposes, I am setting up a simple Ruby gem that will compile some Rust code while handling C extensions. The end goal is for both languages to work together seamlessly and print simple statements.
00:11:05.380 Defining the gem follows standard procedures that many developers are familiar with. Most Ruby gems include an `ext` directory for C extensions.
00:11:45.270 The actual source code for this gem is organized with conventions that might seem awkward but simplify the compilation process.
00:12:29.210 The `extconf.rb` file serves as a DSL, originally intended for RubyGems, which facilitates the creation of a Makefile.
00:13:05.760 Through `extconf.rb`, I've established the connections by defining libraries and entry points necessary for Rust to operate within Ruby.
00:13:50.770 When setting up the native extension, familiarity with Ruby's handling of C extensions is invaluable. In this process, several functions need to be defined, which will ultimately be implemented in Rust.
00:14:38.940 In summary, writing native extensions requires an understanding of C's calling conventions for Ruby, which can be a complicated affair.
00:15:27.369 Now that we understand how to set up the gem let’s jump into some Rust code. The tooling in Rust closely resembles Ruby’s, and it’s fairly straightforward to set up the Rust environment using Cargo.
00:16:29.110 Similar to Ruby’s Bundler, Cargo simplifies the process of managing dependencies and compiling modules.
00:17:16.160 For this integration, Rust uses annotations to declare external functions, ensuring that they are compatible with C. This sets us up to successfully call Rust functions from Ruby.
00:18:07.450 Next, let's see how Rust's functions are invoked and confirm that we can interoperate effectively between Ruby and Rust.
00:18:48.300 In our case, we intend to demonstrate how to print 'Hello, World!' using these integrations.
00:19:31.650 Once we’ve established the integration between Ruby and Rust, we can run our code, which is expected to print results on the screen.
00:20:15.600 This gem allows us to combine the power of Rust with the ease of Ruby while maintaining the simplicity and beauty of either language.
00:21:02.950 For more dynamic programming, we can look into how we can further optimize the communication between Ruby and Rust using features like shared object libraries.
00:21:50.872 We can also use Ruby's Fiddle library to avoid the overhead of creating complex C extensions.
00:22:32.200 With Fiddle, we can dynamically load shared object libraries and access their methods seamlessly from Ruby.
00:23:06.200 I encourage everyone to experiment with these tools and methods to deepen their understanding of integrating Rust into Ruby projects.
00:23:52.200 Additionally, I want to highlight M Ruby, a new project that brings Ruby more inline with being embedded in other languages like Rust.
00:24:54.540 In conclusion, whether you're a seasoned Ruby developer looking to expand your toolkit with Rust or someone completely new, both languages can coexist and provide unique strengths.
00:25:36.730 Thanks to everyone for your time today, and I look forward to discussing further or answering any questions you might have.
00:26:23.900 And with that, I guess I can entertain a few questions if anyone has any. Also, it's always fun to share stories about programming tattoos! Mine is a Ruby tattoo on my arm that I love dearly.
00:27:05.900 Thanks for the warm reception, everyone! Feel free to catch me anytime during the conference.
00:29:07.539 Okay, let's head out and celebrate the end of the event!