00:00:24.160
Hi everybody, I'm Steve. I am here to talk about both Rust and Ruby, two programming languages that I love.
00:00:31.009
I updated my abstract a little since it was submitted for the program, so this talk will be a bit more high-level.
00:00:37.790
I'm going to provide a brief language tutorial since I have 45 minutes, but it won't strictly be about teaching you an entire programming language in that time.
00:00:48.920
What's important is that I want to teach you why you might want to learn about Rust and how learning Rust can help you improve your Ruby development.
00:00:56.000
So, that's the focus of this talk: what Rust can teach us about Ruby.
00:01:02.300
Let me briefly cover my background.
00:01:07.520
I'm a former Rails contributor, ranking around 35th all-time before I stepped back from that.
00:01:13.130
Now, I work for Mozilla on the Rust programming language as my full-time job.
00:01:18.530
I love it a lot; it's great, and I have read all the documentation.
00:01:25.399
So, when you inevitably check out Rust, if you can't figure it out, I apologize in advance, as that would be my fault.
00:01:36.320
Now, let's talk about abstraction. The fun thing about programming languages, in general, is that they are built on abstractions.
00:01:44.000
We discuss abstractions frequently, considering ways to create new ones and manage existing ones.
00:01:49.820
We often categorize abstractions as good, bad, or leaky. Fundamentally, abstraction underpins programming languages.
00:01:57.979
Interestingly, everything can be framed as an abstraction.
00:02:03.229
We tend to think of abstractions as existing in levels, which leads to phrases like 'Turtles all the way down'.
00:02:08.899
However, abstractions are not strictly hierarchical or tiered.
00:02:14.989
In programming terms, we often refer to Ruby as a high-level language and C as a low-level language.
00:02:21.530
Yet, from the perspective of an electrical engineer, C could be viewed as high-level, while assembly would be low-level.
00:02:26.600
This relativity shapes how we categorize programming languages.
00:02:33.230
For example, Rust can handle low-level tasks like C but offers high-level features akin to Ruby.
00:02:39.209
So, is Rust a low-level or high-level programming language? This is where the abstraction hierarchies become muddled.
00:02:45.630
An enlightening example is that you can develop abstractions in divergent ways.
00:02:52.349
You start from the same premise and can arrive at seemingly incompatible conclusions.
00:02:58.470
In computing, you can think about computation mathematically or through the assembly and machine code.
00:03:05.190
Interestingly, modern processors don’t even run assembly or machine code directly but utilize microcode.
00:03:10.950
This means there’s a programming level beneath assembly, linking to physical transformations in hardware.
00:03:16.049
This chain eventually leads to areas where complexity overwhelms, leaving us uncertain about how things work.
00:03:21.299
Thus, thinking about abstraction reveals its universality.
00:03:28.590
Right now, I'm using an abstraction to convey my thoughts through English.
00:03:33.630
I'm translating ideas in my brain into a structured language, which others then interpret.
00:03:40.680
As we know, this process can encounter bugs, and the output isn't always clear.
00:03:46.650
Everything we do is wrapped in abstraction, or what can be considered a lie.
00:03:53.219
A lesson that resonated with me from college is that the fundamental role of operating systems is to maintain this illusion.
00:03:59.550
For instance, every program on your computer believes it is the only program running.
00:04:05.129
It assumes access to the entire memory space, even when that isn't true.
00:04:11.580
The operating system utilizes virtual memory to manage this illusion, providing the impression of infinite RAM.
00:04:17.639
A funny memory from my childhood: I saw an ad for a program called RAM Doubler that claimed to double your memory.
00:04:24.990
Being a nerdy kid, I was skeptical, knowing it was a virtual memory implementation.
00:04:30.539
This program allowed the Mac OS to mimic virtual memory, which was vital in a time of limited memory.
00:04:37.499
Essentially, every action we undertake is enshrined in this tapestry of lies.
00:04:42.839
One of my favorite sayings is that another term for 'eventually consistent' is 'inconsistent'.
00:04:50.529
Why are these lies acceptable? Ultimately, we can only process so much information at any given time.
00:04:57.919
If I had to consider quantum mechanics while moving my hand, it would be a daunting task.
00:05:03.469
So, we create abstractions that allow us to overlook certain details.
00:05:08.479
It's impossible to consider every detail all the time.
00:05:14.289
What I aim to discuss today is a bit about Rust and Ruby!
00:05:19.959
I'd like to help you develop a more intuitive understanding of Ruby internals.
00:05:27.630
I will present abstractions, leading me to build some delightful lies.
00:05:33.790
This slide is necessary because I gave this talk for the first time last week.
00:05:40.650
I realized that Koichi Sasada, the author of MRI, was in the audience.
00:05:47.930
I felt it necessary to preemptively apologize for potentially misrepresenting his work.
00:05:54.110
Fortunately, Koichi provided valuable feedback, which I've now incorporated.
00:06:00.289
If you're interested in this topic, I highly recommend Pat Shaughnessy's book, 'Ruby Under a Microscope'.
00:06:06.450
It beautifully explains how Ruby works and serves as a great introduction to programming languages.
00:06:13.920
Ruby was designed for programmer happiness; that's what Matz had in mind.
00:06:19.060
To achieve this happiness, some performance details were overlooked.
00:06:25.570
Thus, we find Ruby slow compared to many programming languages.
00:06:30.920
However, we must remember that comparisons of language speeds relate to their implementations, not the language itself.
00:06:37.670
For example, JRuby is considerably faster, showcasing differing Ruby implementations.
00:06:44.680
So why is Ruby perceived as slow?
00:06:51.360
Let's discuss some internal mechanics and decisions that contribute to Ruby's performance.
00:06:58.020
Initially, a Ruby program processes a code input through the interpreter.
00:07:05.889
The first step is tokenization, where the code becomes a sequence of tokens.
00:07:12.840
The parser then checks for valid order and coherence among these tokens.
00:07:18.680
For instance, an invocation like '+ 2 2' is valid in that tokens exist, yet lacks correct ordering.
00:07:25.370
The next stage is compilation; Ruby compiles parsed representations.
00:07:31.760
This compilation can lead to confusion, as Ruby does compile its operations.
00:07:39.380
Ultimately, compiled code runs on MRI, Matsumoto's Ruby interpreter.
00:07:46.090
A significant difference introduced from Ruby 1.8 to 1.9 is this compilation step.
00:07:53.120
Ruby interpreters are limited in their understanding of Ruby; they function as separate virtual machines.
00:07:59.260
The interpreter transforms Ruby code into instructions that the VM utilizes.
00:08:06.200
This process often involves working within Docker containers or cloud VM images.
00:08:12.860
This metaphor of multiple layers of machines is aptly illustrated when considering programming.
00:08:19.150
To better visualize these steps, here's a practical Ruby example.
00:08:24.510
The operation '2 + 2' is valid, and when executed, the code gets tokenized.
00:08:30.580
Tokenization translates '2 + 2' into a representation consisting of two integers and a plus operation.
00:08:37.660
Parsing converts it into an abstract syntax tree (AST), structuring the operation for the interpreter.
00:08:43.910
This AST eventually compiles into MRI bytecode for execution.
00:08:50.150
The interpreter processes each step, running the plus operation in an adorable sequence.
00:08:57.550
Now, let's compare Ruby's internal workings with those of other languages.
00:09:04.670
Most programming languages operate under a similar model of tokenization, parsing, and compilation.
00:09:10.630
However, the distinct ways of representation give rise to unique programming styles.
00:09:17.560
For example, in human languages, certain expressions may be simpler in one language compared to another.
00:09:24.930
German offers compound words describing detailed concepts, which English likes to unpack through long explanations.
00:09:30.559
In Japanese, verbs always come at the end of the sentence, creating entirely different constructs.
00:09:37.629
Thus, across different languages, programming goals often change in response to particular features.
00:09:43.820
The focus of my discussion will revolve around performance comparisons.
00:09:50.000
Let's delve into the intrigue of Rust as a programming language.
00:09:56.150
As a small visual joke, I’ve playfully added 'st' to the top of Ruby.
00:10:04.410
I jokingly mentioned that I'm only programming in languages starting with 'ru'.
00:10:10.530
In the Rust community, we affectionately refer to our crab mascot, Ferris.
00:10:18.440
Rust is an ahead-of-time compiled programming language.
00:10:25.020
This means that rather than interpreting the code each time, you compile it once.
00:10:32.400
With Rust, when you call the Rust compiler on a file, it outputs a standalone program.
00:10:38.470
In contrast to Ruby, where every execution involves tokenizing, parsing, and compilation.
00:10:44.640
There’s an overhead in dynamically interpreted languages that ahead-of-time compilation can circumvent.
00:10:51.510
However, this isn't a strict limitation; other practices can manipulate these models.
00:10:57.820
For example, one could pre-generate the MRI bytecode and load it on demand.
00:11:04.150
Thus, the methodology and culture of a programming language greatly influence how efficiently we can code.
00:11:11.229
Let’s discuss how methods are called in Ruby.
00:11:19.060
The operation 'foo' can be complicated, and for those unfamiliar with Ruby's method resolution, here's a diagram.
00:11:26.300
In this process, we check the current object's method table, searching for our method.
00:11:33.040
If the method isn't found, Ruby checks parent classes, continuing this resolution process.
00:11:39.260
If Ruby fails to identify the method, it’ll invoke 'method missing,' essentially allowing for flexibility in method calls.
00:11:45.860
So, this can lead to unforeseen complexities in understanding method behavior.
00:11:52.320
Time to present an example: a simple Ruby function accepting one argument that returns five.
00:11:58.960
Ruby must navigate its complex method resolution when invoking the function.
00:12:05.530
Next, here's a Rust equivalent to illustrate a stark contrast.
00:12:11.020
The Rust function is clearer, detailing its types and functionality without ambiguity.
00:12:18.520
In Rust, you must define the entry point of your program with the 'main' function.
00:12:24.860
The approach is simpler, with explicit types leading to more stringent control.
00:12:31.410
Rust compiles down to assembly code involving a straightforward sequence of instructions.
00:12:38.529
The assembly structure is often succinct and readily understandable.
00:12:45.210
Much effort in Rust emphasizes low-level programming comprehensibility.
00:12:52.140
Perception of difficulty differs among programmers; what might be simple for some may appear complex to others.
00:12:57.840
Many find assembly code intuitive compared to high-level frameworks like Rails.
00:13:05.780
There are different strengths and weaknesses in programming, affecting preference in language choice.
00:13:12.160
I’m interested in showcasing various Rust and Ruby functionalities.
00:13:18.640
In Ruby, one can instantiate a class, form its attributes, and define a return statement.
00:13:25.680
Rust takes a different approach—favoring structures and implementations.
00:13:30.840
This diverges significantly from Ruby’s object-oriented expectations.
00:13:37.789
In Rust, you define a structure and then implement the behavior separately.
00:13:44.130
Using Rust, this delineation fosters clarity of data and behavior.
00:13:50.580
The compilation yield is more concise, leading to optimized performance.
00:13:56.900
So, expect a multitude of assembly lines from Rust.
00:14:03.300
Optimizations are possible, enhancing generated code performance.
00:14:09.490
Rust’s compiler leverages optimization strategies to enhance execution efficiency.
00:14:16.030
Ruby, conversely, performs limited optimizations as a general rule.
00:14:23.080
Let’s examine how Ruby operates in comparison to Rust.
00:14:28.750
In Ruby, we specify class behavior through modules and mix-ins.
00:14:35.600
So you can build classes to achieve desired functionality through behaviors.
00:14:41.770
In contrast, Rust implements traits and structures distinctly.
00:14:47.900
The separation of attributes and behaviors creates limitations.
00:14:53.210
There is explicit type binding in Rust, which results in rigorous methods.
00:14:59.590
This leads to reduced ambiguity when executing function calls.
00:15:05.620
While flexibility exists in Ruby, it’s crucial to define traits in Rust clearly.
00:15:12.340
By requiring the method to be defined, Rust grants more safety in function calls.
00:15:19.540
So, Rust brings type safety and structure that Ruby may lack.
00:15:26.590
With this rigidity comes better performance, reducing overhead.
00:15:33.420
Let's explore some practical code comparisons next.
00:15:36.900
When we write functions in Rust, they need clear parameter types.
00:15:42.690
Rust captures implementations efficiently while retaining program clarity.
00:15:49.739
Moreover, a brief glance at these structures clarifies programming intentions.
00:15:56.050
Let’s wrap this segment by underscoring the necessity of performance considerations.
00:16:05.340
The message here is that Rust excels at performance where Ruby slows.
00:16:11.790
Ruby, despite its slow nature, remains beloved by many developers.
00:16:18.570
Both languages possess unique advantages; exploring both can enhance your skills.
00:16:25.200
We often misjudge programming languages, causing unnecessary conflict.
00:16:33.459
Embracing the distinctions among languages is vital for new programmers.
00:16:39.569
It's frustrating to see individuals demonstrating disdain towards others’ chosen languages.
00:16:44.970
In crucial ways, every language adds value to the programming landscape.
00:16:51.740
This promotes exploration and trying out new languages whenever possible.
00:16:57.140
I encourage everyone to appreciate the multifaceted nature of coding.
00:17:03.650
Let’s foster a culture of exploration and curiosity, rather than resentment.
00:17:10.130
Ultimately, programming languages ought to unite rather than divide us.
00:17:16.560
Now, I’ll take a moment to present additional Rust functionalities and discuss their merits.
00:17:23.389
Rust shines in the realm of safety and performance, especially in systems programming.
00:17:29.920
Rust helps developers create reliable, efficient applications, reducing runtime errors.
00:17:36.389
Ruby developers can also benefit from understanding Rust's functionalities.
00:17:42.820
This perspective opens the door to reduce bottlenecks while harnessing Ruby's expressiveness.
00:17:50.010
By leveraging Rust, it's possible to add performance to Ruby applications without sacrificing ease of development.
00:17:56.270
Thank you, everyone, for being an engaging audience!
00:18:00.600
I'm happy to take any questions!