00:00:12.620
So, 30 minutes is a really aggressive timeframe to introduce a group of people who don’t have much context for this. I might go a little fast—hopefully not too fast—but you should think of this talk as a jumping-off point for your interest in Rust. If you become interested, there will be a few things mentioned that you could explore further. I’ll be writing a blog post over the next few weeks that discusses how to specifically integrate Rust into a Ruby on Rails application. However, I won’t be discussing that today because it's a whole other topic. But if you leave this talk feeling that you really want to use Rust for something practical, that blog post will be a good resource. So keep an eye out for it on the Skylight blog.
00:00:48.480
I think a lot of people view programming languages through this quadrant grid. You may have seen when they announced Swift, for instance, Apple created one of these grids. Despite its silliness, I don’t believe Ruby is faster or more performant than JavaScript, and I don’t really understand these quadrants completely. Yet, people do tend to think about the world in these terms. If I were to give a talk about Rust and I weren't me, I might try to place Rust in one of these quadrants. The reason I’m showing this is that I think it’s a poor way to approach programming in general. The only constant in programming is change. Many people have a fixed idea of a trade-off between performance and productivity, imagining that if you gain a bit more productivity, you must sacrifice some performance. However, if we look at reality—let’s say in 2005—JavaScript was a reasonably productive language, albeit not very fast.
00:01:42.030
Fast forward ten years, and one would expect that since JavaScript hasn’t really changed much in terms of productivity, it hasn't gotten faster either. But that’s not what actually happened. JavaScript became a bit more productive with ES5 and ES6 features, and it became significantly faster. In reality, every programming language that sticks around tries to find ways to improve productivity without sacrificing performance. So, instead of moving down and to the right, where you lose performance as you gain productivity, every language is actually striving to move up and to the right.
00:02:33.080
When a language evolves significantly, or when a new language emerges that's markedly different from others, it can enable a new generation of programmers to accomplish tasks they couldn’t tackle before. JavaScript is a great example of this: it initially started as a slow language, but as JavaScript became faster and more user-friendly, it paved the way for a new generation of frontend developers to write back-end code. You could say, 'I don’t want my jQuery developers writing back-end code,' but that perspective overlooks the shifts in the programming landscape that empower large groups of people to do things they weren’t able to do before.
00:03:00.930
Rust aims to achieve a similar effect. It is a new programming language trying to empower individuals who may not have previously felt confident to tackle low-level systems programming. Prior to Rust, programming languages essentially fell into two categories: safe languages, where your program was unlikely to crash if there are no bugs in the compiler or interpreter—like Ruby or Python, thanks to their garbage collectors—and unsafe languages like C or C++, which provided more control over memory but required a high level of expertise to avoid pitfalls such as segfaults. Rust attempts to strike a balance by offering the safety of languages like Ruby without the mandatory overhead of garbage collection, allowing developers to manage memory directly when necessary.
00:04:26.000
Eliminating the possibility of crashes represents a huge shift in programming ergonomics. If you can program without fear of crashing, it fundamentally reshapes what's possible. This leads to my perspective that we should always look for shifts in the programming landscape. With Rust, the combination of direct memory control and safety empowers new generations of systems programmers. It invites individuals who may previously have shied away from low-level systems programming to engage.
00:05:37.970
Before Rust, many people identified with high-level languages. We talk among ourselves about why we find these languages productive. A common refrain in the high-level programming community is 'YAGNI', or 'You Aren’t Gonna Need It.' This often is true regarding features we don't need, but I argue that performance should be an essential consideration. Sometimes, better performance is critical. For example, when someone says they need 60 FPS, or are concerned about jank, real-time systems, or high-frequency trading, they need predictable performance and control that surpasses what a garbage collector provides.
00:06:11.829
Whenever anyone mentions needing less memory or is writing a cross-platform library like LibSass (which is meant to be embedded in various systems), it's apparent that performance matters. Additionally, as you delve into programming language internals, when reading any C code or understanding JavaScript JIT, the true value of performance becomes evident. Not having to concern yourself with performance is a significant blessing in many cases, but when performance does matter, your ability to do so effectively becomes complicated without having expressive tools in your programming language.
00:07:02.350
The point of a programming language is to allow us to communicate our intentions with other individuals regarding our goals.
00:07:42.550
As Dave Herman, who founded Mozilla research, articulates, when performance becomes crucial, it becomes part of the communication domain for you and your collaborators. You require a language that expresses your performance needs clearly. It is true that not every situation requires concerns regarding performance. If the performance requirements are negligible, investing time in Rust for a specific problem may not be the best use of your time. However, when performance truly matters, such as projects like Skylight, where I ultimately became immersed in Rust, that explicit communication about performance requirements is immensely beneficial.
00:08:58.560
Now, delving into what Rust is, I can discuss low-level performance, but I'd like to focus more on high-level productivity, which may resonate more with a Ruby audience. One crucial principle in Rust is 'zero-cost abstraction.' This concept may sound a bit like snake oil, but it means that when you introduce an abstraction in a programming language, if you're not careful, you introduce some minimal cost. As the complexity of your abstractions grows, like in large frameworks such as Rails, that cost compounds.
00:09:54.080
The goal behind Rust is to identify abstractions you can enable without introducing much—and ideally zero—additional cost. This ability allows you to write fairly abstract programs without suffering significant performance penalties. This is an appealing aspect of Rust: even if you don't take safety into account like in programming languages such as C, the challenges presented by their complexities make abstraction difficult.
00:10:42.370
To illustrate this idea, consider the example of the blank method in Ruby string implementations, which I pulled from ActiveSupport. This method checks if a string is 'blank.' In Ruby, performance dictates certain decisions that involve regex checks, dynamic typing, and class certainty. In contrast, if you were to implement similar functionality in Rust, everything is statically typed. For example, if we want to define a 'blank' method, we might create a trait called 'IsBlank' and define an associated function, akin to defining a class method in Ruby.
00:11:55.660
To implement the trait for a string, in Rust we specify that it returns a boolean indicating whether the string is blank. This immutability aspect offers more sophistication in Rust. The implementation can further extend to check against fixed-size arrays and even utilize Rust’s options for nil-checking. In Rust, when you implement traits for user-defined types, it adds flexibility comparable to how Ruby handles its `'blank?'` check. But in Rust, the elegance lies in how flatly the traits connect without invoking costly allocations.
00:12:38.390
For instance, in Rust, implementing a blank trait allows you to create generic structures effortlessly. Hence, similarities between Ruby’s setups and Rust’s allow for a progression in usability and efficiency. You can perform similar actions without having to perform unnecessary lookups or allocations, allowing the compiler to generate optimal, runtime-specialized code.
00:13:31.640
What I find compelling about Rust is the iteration process: Rust's iterators and lambdas encapsulate powerful expressive features without sacrificing performance. If you’ve written Ruby or JavaScript, you know the strength of using blocks to abstract various processes. Rust provides lambdas alongside iterators, which you may liken to lazy enumerators in Ruby. For example, when you create a range from 0 to 100 and apply filters or mapping functions, you find Rust allows clean and concise abstractions.
00:14:29.710
Like dynamic languages, Rust enables you to operate at a high level while minimizing memory usage. The iterators in Rust are lazy as well, garnering no intermediate objects and avoiding additional allocations. Each operation of 'map' or 'filter' is treated as generating a specialized version of the underlying method or function based on the type of data it consumes, leading to efficient performance execution without the runtime complexity found in other languages.
00:15:15.050
Another interesting consideration is Rust's approach to error-checking and safety features. Rust's design assures that when you define a method that reads a certain type, it is specialized for that type at compile time. This process enables the compiler to optimize function calls without sacrificing performance or safety. It does not require additional memory for virtual method tables, as often seen in other languages. Its generics facilitate a powerful blend of flexibility and performance while keeping memory concerns minimal.
00:16:15.690
Reflecting upon the combination of the zero-cost abstractions, iterators, and traits, Rust offers high-level productivity alongside the robustness and performance of low-level systems programming. These features present a unique capability for programmers to engage effectively with systems programming across various applications.
00:17:13.160
As I previously alluded, the safety embedded in Rust is pivotal for programmers hesitant about delving into low-level programming. Ownership, in particular, is a core concept—it delineates the rules governing pointers and memory management. While this concept appears daunting at first, it safeguards robust memory efficiency that averts many common pitfalls found in languages like C or C++. When you follow Rust's ownership principles, you gain correct and efficient programs that are deeply engaging.
00:18:34.520
Returning to the importance of Rust in today's programming landscape, it opens the door for programmers who would otherwise hesitate to approach low-level coding—like myself. My previous experiences with C programming often led to anxiety about memory management, but Rust alleviates these concerns by enforcing strict ownership rules. With Rust, you can address performance-related areas effectively and experiment without fear of crashing your application.
00:19:39.900
When performance becomes a priority—for instance, in high-frequency trading applications—this ability to control your memory management without overhead becomes a competitive advantage. Ultimately, Rust presents a compelling framework to a new generation of aspiring systems-level programmers, erasing prior hesitations in tackling low-level code. It serves as an invitation to these developers to ask themselves what new possibilities they might unlock with this power.
00:20:52.660
In conclusion, I believe Rust's integrated safety and productivity features stand out in the programming landscape. The language encourages the integration of systems programming with a depth previously reserved for only the most experienced engineers, enabling the exploration of high-performance applications without sacrificing safety. Thank you for your time.