Hacker News new | past | comments | ask | show | jobs | submit login
Rust in Production (2018) (figma.com)
112 points by mromanuk on March 22, 2019 | hide | past | favorite | 34 comments



Things that have changed:

- NLL (non lexical lifetimes) are now in stable, so working with lifetimes and references is a bit easier

- stack traces: failure is still around, it's got a fairly large group using it, it seems. I prefer the std error handling route most times.

- async is hard: it's still pretty hard


Unfortunately failure and errorchain appear to not be cool anymore (ie I've noticed quite a few people are migrating away from failure just like they did from errorchain) and there doesn't appear to be any push from the Rust team as of yet.

I think it's a serious problem as your code base grows and I wish we had some more work on the RFC front.


Given the vanilla error handling is my favorite of the lot, I don't really consider it a bad thing that people are moving away from it.

There are some downsides, like the lack of stack traces, but it's a nice pattern. Does it have to be 'one size fits all'?


quite smart approach of having a nodejs frontend doing what it's good at (async) calling the backend via simple subprocess/stdio communication. they could almost say they invented CGI :)


My first thought too!

It seems like the speedup they gained was probably as much from the architecture change as it was rust. (That often seems to be the case when people say they saw a significant speedup due to switching to rust, go, or similar.)


> calling the backend via simple subprocess/stdio communication

why is this faster/better than the frontend calling the backend through say, nginx proxy_pass or REST HTTP calls?


I did this recently, where I compared going through FFI from Java to Rust, vs through gRPC. gRPC wasn't that much slower than FFI, and its benefit would be that I could have 2 services in the network.

FFI had overhead, but its performance profile was consistent, very little fluctuation in runtime.


Did you also test HTTP? Did you publish these results anywhere?


They're forking a new process for each request. Passing the request data to that process on stdin when you create it is much simpler than spawning a process, waiting for it to be ready, and then communicating with it via http.


> They're forking a new process for each request.

Hm, I don't think they are. I think they one persistent process managing the state of each document, and many requests might interact with that document, via stdin/stdout channels on that document's process.

Makes the case for the rest of what you said all the stronger, though.


Overhead.

Nginx/rest involves the ipstack.


Isn't there overheard in spawning processes?


In-process is faster.


Anyone know if the first con listed has improved with the introduction of non-lexical lifetimes?


I would say it has improved quite a bit, but they are still there. It varies quite a bit on what you are doing. At work we have a modest sized project, converted from C, being used and updated for about a year. I don't think it has had any significant lifetime battles; I don't think there are even explicit lifetimes in the source.

Data structures exercises will be a different story.


I'm not the author, but from my perspective: Yes. Dramatically. Non-lexical lifetimes eliminated the most common cases where the compiler was just wrong.

Of course you still need to think about lifetimes, and sometimes warp your program around them. However, it is now much less common for that thinking to arrive at "The compiler is wrong; how can I convince it of that?"


The specific problem he is referring to should now be fixed with NLL, yeah. That doesn't mean lifetimes aren't still hard to learn at first, though.


Rust seems like the right answer for a lot of things except writing servers. For that, Elixir with its Erlang VM seems like a better answer.


I've been writing servers in Rust and I don't really agree. Granted, these may not be traditional HTTP servers - they're AWS lambdas, which puts them closer to the "some function" than "some server" depending on how you look at it.

They work great, I've been able to iterate extremely quickly on a system that has had its requirements changed quite a lot over time.

I haven't spent much time optimizing my code at this point but they execute extremely quickly, much faster than my Python lambdas.

Regarding the author's complaints:

I haven't needed any async. I use threads and it's fine. When async/await is a thing I'll use it, maybe - I really don't think it's going to make a difference but it might free up some memory that I can throw at caching.

Error handing in Rust is still a bit uncomfortable. The failure crate has been working for me but it doesn't always feel 'right'.


> they're AWS lambdas

those are not servers! In fact the branding of AWS lambda is exactly "serverless". You don't have to have process restart logic, they're very transient, if a process error causes a crash (yes that happens even in rust) the entire thing is taken down. They're less of a server than a kubernetes-orchestrated container.


Sure, sorry, I meant services where I wrote "servers" and it's likely the person I responded to did as well.

I don't think it changes anything about what I said - process restarts aren't something I'd care about the language for anyways, I'd have a sidecar for that.


Hey there, yes. I guess I meant "services" / servers. I suppose from my point of view - small fish in the ocean - I suppose Rust services running on lambda would be a-ok.

I'd love to learn more about how you build and deploy. Do you have any favorite articles / resources that I should look at?


Here’s my favorite success story about Rust on lambda: https://andre.arko.net/2018/10/25/parsing-logs-230x-faster-w...

This is before they offered official support though. Here’s the announcement for that, which links to resources: https://aws.amazon.com/blogs/opensource/rust-runtime-for-aws...


Hey, thanks! =)


https://insanitybit.github.io/2018/11/05/deploying-grapl-wit...

Here's a post on how I use AWS's "Cloud Development Kit" to do my deployments. Builds are through Docker.

Source code: https://github.com/insanitybit/grapl


Right on! Thank you =)


Are you aware of actix? What do you think of it?


It's pretty nice, it even feels a bit like Node.js' express. It's pretty easy if you can answer requests quickly/synchronously.

When you need to use Futures, it's a bit more fiddly (you can't wing it, you really need to understand lifetimes and how the Future types are composed). I'm hoping the upcoming async/await syntax sugar will lower the barrier to entry here.


I'm not aware, to be honest. I'm only now learning Elixir for a few weeks now and plan on taking up Rust next after building a small Elixir project.

What I found was: - Elixir, has awesome support for concurrency and zero-downtime deployments. Runs on Erlang VM. Inspired by Ruby.

- Rust - replacement C/C++ as the low-level programming language of the future for people who want to write pretty code.


> has awesome support for concurrency

so does rust.

> Rust - replacement C/C++ as the low-level programming language of the future for people who want to write pretty code.

It's not just that, it also replaces say python or ruby on the serverside.

> write pretty code.

Yeah, no, it's for people who want to be productive in a low level language.


The erlang vm is explicitly designed for concurrency. I wrote the raft protocol in elixir in about 300 lines of code.

Rust is great, but it's pretty hard to argue that any language has more awesome support for concurrency than the beam languages.


Ok let's talk concrete implementation.

Rust: https://github.com/pingcap/raft-rs LOC: 15417

Erlang: https://github.com/rabbitmq/ra LOC: 18012

Lines of code is not the only metric. I'm actually really curious about Erlang and Elixir but to be honest I do like type systems a lot. I also like the idea of idk...having one language for my os, db, front-end.


Unfortunately I can't show you my code since it's closed. Just looking at the two codebases, about half of the erlang implementation is static typechecking hints, and I don't know if GitHub counts the documentation HTML as LOC.

As an example of convenient concurrency, in Erlang vm gives you process node id translation. What that means is that if you're sending a message between threads in two instances in a cluster of VMs, you can send your the mailbox address of your local thread and have it converted on transmit to the equivalent remote thread address on the remote machine. Literally one less thing you don't have to worry about, and clustering is a first class citizen in the language, no libraries necessary.

Basically, the dev process was, I wrote my raft implementation, tested it locally and extensively (including property tests) using multiple local threads, and did almost nothing (three lines of code to provide a mailbox Oracle) and had a solution that worked across the network.

If you're curious about BEAM languages, I wouldn't worry about type systems. If anything I think hypercorrectness in the languages leads to a false sense of comfort about the quality of your code that can get in the way of building resilient, designed to fail gracefully systems. Typechecking can catch errors early and save you dev and debug time, but static typechecking is probably enough for about 80% of those concerns.

Erlang languages come with static typechecking. It's kind of a pain in the butt out of the box. I don't know about erlang, but if you code in vscode, the elixir_ls plugin engages the static typechecking in such a transparent fashion that I've forgotten to install the makes-static-typechecker-easier library and it's caught code problems for my junior dev (who I haven't taught typechecking yet). Despite it being optional in the language, the vscode plugin makes it ever so ugly to not annotate types that my very minor obsessive tendencies lead me to annotate everything.


I'm just learning Rust right now and my initial thoughts are exactly your sentiment. Writing a backend for Websockets is so easy in Erlang/Elixir, seems a lot more difficult in Rust.

Now, the performance of Rust is aspect that Erlang/Elixir will never close to reaching.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: