Tag: #rust
Video: My VM and its time-travelling debugger
My work at Zoo has recently focused on KCL, our CAD programming language. Currently our modeling app uses a tree-walk interpreter, but for various reasons we've been exploring a proper compiler instead. I've been developing the compiler, called Grackle. It compiles to a bytecode VM (i.e. an abstract machine), called the KCVM. I gave a 10-minute presentation about KCVM and its time-travelling debugger at a tech talk in Austin recently. Here's the recording!
Thanks very much to Jam.dev for hosting the event!
Video: Error handling
The fourth Rust Club video is up! Every Monday I teach Rust to my coworkers at zoo.dev on video chat. We record the call and put it on YouTube so you can learn too. This week's video is about different ways to handle errors in Rust -- when should you panic and when should you return a Result::Err? And what type should that Result::Err be?
Apologies for the low video quality, starting from next episode we used a better-quality recording system.
Video: Analyzing performance
KittyCAD's third Rust Club video is up! We analyze how fast the demo parser from my [first video][/winnow-basics] is, and find ways to speed it up. We use benchmarks to measure its speed, and flamegraphs to visualize its runtime, to find places we can improve.
Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Starting from episode 5 we used a better-quality recording system.
Investigating crazy compile times
I hate long compiles. I spend hours of my time trying to reduce minutes of compile-time. I recently noticed that the KittyCAD Rust API client was taking an incredibly long time to compile in release mode. Weirdly, the compile time in debug mode was totally fine. I managed to shrink the release compile-times from 33 minutes to 1.5 minutes. Here's how.
Video: Parsing a programming language
KittyCAD's second Rust Club video is up! My [first video][/winnow-basics] covered the Winnow library for parsing text. Today's video shows you a real-world parser example. I'm working on the KittyCAD language (KCL) for designing CAD models, and this reviews the tokenizer and parser I wrote recently.
Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Starting from episode 5 we used a better-quality recording system.
Interviewed at Filtra.io
I had a great time talking to Drew of filtra.io! We talked what KittyCAD does and why we're all-in on Rust. We also get into my past at Cloudflare and why there's so much Rust there. Check out the piece here.
Video: My P99Conf talk on Rust backends
I had a great time presenting at P99Conf! I watch their talks every year and I always learn a lot. I was really thrilled to present a talk at this year's conference. It's heavily based on my blog post Why use Rust on the backend?. If you missed the talk, you can watch the recording or view the slides here.
Video: Parsing text with Winnow
I work at KittyCAD, and every Monday I teach Rust to my coworkers for an hour. We always record them, so that over time we build up an archive of Rust learning videos. Recently I realized we should put some of them on the internet, because other programmers outside KittyCAD might find them helpful too!
This is our first episode, and it's about building parsers with Winnow, a new fork of Nom. I'm a big fan of Nom, and I've written about it a lot. I've been interested in Winnow since it was announced, so here's an hour-long explanation of how to use Winnow.
Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Future episodes should have higher video quality!
Rustconf 2023 recap
I got back from Rustconf 2023 last week, and I had a great time! I thought I'd write up my impressions of the conference, for anyone curious about what it's actually like.
Why use Rust on the backend?
I read and liked Andrew Israel's I love building a startup in Rust. I wouldn't pick it again. It makes a lot of sense! He basically says that his startup prioritizes developer productivity over performance. Sensible choice for a start-up founder to make. If Rust is going to slow your developers down, and you don't need its benefits, then you should definitely consider using a different language.
On the other hand, I've been using Rust as high-level language at Cloudflare for a few years now. By "a high-level language" I mean one where performance doesn't really matter much. I've mostly been using it for API servers, where overall latency doesn't really matter too much. I'd be totally fine using a garbage collected language, or an interpreted language, because I don't need to eke out every last microsecond for blazing fast performance. I just want my server to stay up, do its job, and let me ship features quickly.
So why use Rust for a task like that? Well, although Rust has a reputation for being a low-level systems language, it actually does an admirable job of acting like a high-level language. So here's my list of reasons to consider using Rust, even for a project where performance isn't critical.
I'm on Rustacean Station
Hi all! Allen Wyma of Rustacean Station had me on the podcast to talk about Rust at Cloudflare. We cover why and how Cloudflare started using Rust, how my team specifically works with Rust, and how Cloudflare works. We also go on a big tangent about social security numbers. Give the episode a listen if you'd like.
Illegal satire about Rust
In case you didn't hear, comedy is now legal on Twitter but accounts engaged in parody must include “parody” in their name, not just in bio. Of course, this only made everyone double down. So yesterday, I changed my name to Rust Language and started posting misinformation.
The last week on twitter has basically been "the new 3rd grade substitute teacher can't control the class" and we're all misbehaving. I've changed my twitter back to my real name and face, so I've preserved my fake Rust tweets for posterity here.
Static streams for faster async proxies
Last week in Tokio's Discord chat server someone asked a really interesting question: how can you stream a multipart body from an incoming request into an outgoing request? My struggle to answer this really helped me understand Rust async lifetimes. We'll explore why this is tricky, then design and benchmark a solution.
What are Rust's HTTP extensions?
I learned about extensions when reading the hyper docs. But they also pop up in lots of other Rust web libraries, like http, tonic, and actix-web. So they must be really useful, if so many libraries offer them. But I personally had no idea what they were or how to use them. Today I'm going to explain what extensions really are (a set of values, keyed by type), and how you can use them to pass data between different parts of your web servers (e.g. middleware, routers, and handler functions). I'll give you a real-world example from the gRPC server I'm building at my job.
What I learned from making a DNS client in Rust
Over the last few weeks I built my own DNS client. Mostly because I thought dig (the standard DNS client) was kinda clunky. Partly because I wanted to learn more about DNS. So here's how I built it, and how you can build your own too. It's a great weekend project, and I learned a lot from finishing it.
Parsing DNS headers with Nom
In the last blog post, we learned how to parse binary, bit-by-bit with Nom. I really wanted to give a real-world example of binary protocols, so here's one from Dingo, a basic DNS client I made.
Parsing bitstreams with Nom
Programming languages generally only manipulate bytes (groups of 8 bits). It can be pretty tricky to manipulate single bits. But sometimes you need to -- for example, a DNS header has some 4-bit numbers, and encodes some boolean flags into single bits. So we really need a way to parse binary data without chunking it up into bytes of 8 bits.
Luckily, Nom can do this! In the last blog post, we learned how to parse text files with Nom. The trick is to start with simple parsers that parse a few characters at a time. Then, using combinators, combine those simple parsers into more complex parsers that can deserialize an entire structured file. We can reuse this approach for parsing binary data too. Let's see how!
Parsing Text with Nom
"Parsing" is turning a stream of raw text or binary into some structured data types, i.e. a Rust type that your code can understand and use. This isn't the textbook definition of parsing, but damnit, this is my blog and my opinion. This tutorial is about nom, my favourite Rust parsing library. It uses a parser combinator approach: you start writing tiny parsers that match, say, a single number or a character. These become building blocks for larger parsers, that match, say, a date or a phone number. By combining many small parsers together, you can build a big parser that decodes a file or stream into nice Rust structs and enums. In this tutorial we'll use Nom to parse the input file to an Advent of Code puzzle.
Pin, Unpin, and why Rust needs them
Using async Rust libraries is usually easy. It's just like using normal Rust code, with a little async
or .await
here and there. But writing your own async libraries can be hard. The first time I tried this, I got really confused by arcane, esoteric syntax like T: ?Unpin
and Pin<&mut Self>
. I had never seen these types before, and I didn't understand what they were doing. Now that I understand them, I've written the explainer I wish I could have read back then. In this post, we're gonna learn
- What Futures are
- What self-referential types are
- Why they were unsafe
- How Pin/Unpin made them safe
- Using Pin/Unpin to write tricky nested futures
Grids in Rust, part 2: const generics
In part one, we defined a Grid trait and implemented it using 1D and 2D vectors. Benchmarks revealed that a 1D vector was a better choice than a nested 2D vector. In this post, we'll write a new implementation that uses arrays instead of Vec. This should be faster!
Grids in Rust, part 1: nested vs. flat Vecs
While making a raytracer in Rust, I needed an efficient way to store the pixels of a 2D image. In this post, we'll compare two different implementations of a 2D grid datatype, dipping our toes into data parallelism with Rayon and benchmarking with Criterion.